From 9a66905fffe4fd0161253b7f3551dcde8331b886 Mon Sep 17 00:00:00 2001 From: Charles Lepple Date: Thu, 6 Aug 2015 22:18:24 -0400 Subject: [PATCH 0001/1232] Rename README with extension for AsciiDoc --- README => README.adoc | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.adoc (100%) diff --git a/README b/README.adoc similarity index 100% rename from README rename to README.adoc From 8271ab0e43b6755d24c6c6394c3555d750d07cfb Mon Sep 17 00:00:00 2001 From: Charles Lepple Date: Thu, 6 Aug 2015 22:31:20 -0400 Subject: [PATCH 0002/1232] Remove some old compatibility information from the README --- README.adoc | 52 ++++------------------------------------------------ 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/README.adoc b/README.adoc index 1b44663d8e..33f61af264 100644 --- a/README.adoc +++ b/README.adoc @@ -476,62 +476,18 @@ The past stable trees were 1.0, 1.2, 1.4, 2.0, 2.2 and 2.4, with the latest stable tree designated 2.6. The development trees were 1.1, 1.3, 1.5, 2.1 and 2.3. As of the 2.4 release, there is no real development branch anymore since the code is available through a revision control -system (namely Subversion) and snapshots. +system (namely, Git) and snapshots. Major release jumps are mostly due to large changes to the features list. There have also been a number of architectural changes which may not be noticeable to most users, but which can impact developers. - Backwards and Forwards Compatibility ------------------------------------ -The old network code spans a range from about 0.41.1 when TCP support -was introduced up to the recent 1.4 series. It used variable names -like STATUS, UTILITY, and LOADPCT. Many of these names go back to the -earliest prototypes of this software from 1997. At that point there -was no way to know that so many drivers would come along and introduce -so many new variables and commands. The resulting mess grew out of -control over the years. - -During the 1.3 development cycle, all variables and instant commands -were renamed to fit into a tree-like structure. There are major groups, -like input, output and battery. Members of those groups have been -arranged to make sense - input.voltage and output.voltage compliment -each other. The old names were UTILITY and OUTVOLT. The benefits in -this change are obvious. - -The 1.4 clients can talk to either type of server, and can handle either -naming scheme. 1.4 servers have a compatibility mode where they can -answer queries for both names, even though the drivers are internally -using the new format. - -When 1.4 clients talk to 1.4 or 2.0 (or more recent) servers, they will -use the new names. - -Here's a table to make it easier to visualize: - -[options="header"] -|============================================= -| 4+| Server version -| *Client version* | 1.0 | 1.2 | 1.4 | 2.0+ -| 1.0 | yes | yes | yes | no -| 1.2 | yes | yes | yes | no -| 1.4 | yes | yes | yes | yes -| 2.0+ | no | no | yes | yes -|============================================= - -Version 2.0, and more recent, do not contain backwards compatibility for -the old protocol and variable/command names. As a result, 2.0 clients can't -talk to anything older than a 1.4 server. If you ask a 2.0 client to -fetch "STATUS", it will fail. You'll have to ask for "ups.status" -instead. - -Authors of separate monitoring programs should have used the 1.4 series -to write support for the new variables and command names. Client -software can easily support both versions as long as they like. If upsd -returns 'ERR UNKNOWN-COMMAND' to a GET request, you need to use REQ. - +The network protocol for the current version of NUT should be +backwards-compatible all the way back to version 1.4. A newer client should +fail gracefully when querying an older server. Support / Help / etc. --------------------- From bf9847c21d3541a0b6a15e5f5aa3f651290a1939 Mon Sep 17 00:00:00 2001 From: Charles Lepple Date: Thu, 6 Aug 2015 22:18:24 -0400 Subject: [PATCH 0003/1232] Rename README with extension for AsciiDoc and update references to it Also: - add 'foreign' to AM_INIT_AUTOMAKE macro so that automake doesn't fail as a consequence of the lack of a 'README' file (since we now have 'README.adoc'); - make sure README.adoc is distributed. --- Makefile.am | 3 ++- README => README.adoc | 0 configure.ac | 2 +- docs/Makefile.am | 4 ++-- docs/user-manual.txt | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) rename README => README.adoc (100%) diff --git a/Makefile.am b/Makefile.am index 77f8627833..17b0dfa449 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,8 @@ SUBDIRS = include common clients conf data tools docs drivers \ lib scripts server tests # COPYING is included automatically. -EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING +EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS README.adoc \ + UPGRADING # ---------------------------------------------------------------------- # flags to pass to ./configure when calling "make distcheck" and "make diff --git a/README b/README.adoc similarity index 100% rename from README rename to README.adoc diff --git a/configure.ac b/configure.ac index 74e0e5b635..b25c806324 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_CANONICAL_SYSTEM NUT_CHECK_OS AC_CONFIG_HEADER(include/config.h) AC_PREFIX_DEFAULT(/usr/local/ups) -AM_INIT_AUTOMAKE([subdir-objects]) +AM_INIT_AUTOMAKE([subdir-objects foreign]) dnl we need Autoconf 2.60 or better to enable features of Posix that are extensions to C AC_MSG_CHECKING(for autoconf macro to enable system extensions) diff --git a/docs/Makefile.am b/docs/Makefile.am index 8ca7afd696..6581600a29 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -76,7 +76,7 @@ clean-local: ### TODO: automatic dependency generation # Add other directory deps (not for local EXTRA_DIST) and generated contents -FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ +FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README.adoc \ ../INSTALL.nut ../UPGRADING ../TODO ../scripts/ufw/README FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ ../scripts/augeas/README ../TODO ../lib/README \ @@ -111,7 +111,7 @@ A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) --attribute icons \ $(A2X) $(A2X_COMMON_OPTS) --attribute=pdf_format --format=pdf -a docinfo1 $< if HAVE_ASPELL -# FIXME: also check ../{NEWS,README,UPGRADING}+other dirs +# FIXME: also check ../{NEWS,README.adoc,UPGRADING}+other dirs # Non-interactively spell check all documentation source files. # This is useful for Buildbot and automated QA processing # FIXME: how to present output (std{out,err}, single file or per target)? diff --git a/docs/user-manual.txt b/docs/user-manual.txt index d25083dc60..fe27cf08ab 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -33,7 +33,7 @@ If you wish to discover how everything came together, have a look at the [[Overview]] -include::../README[] +include::../README.adoc[] [[Features]] From e790480a2b3cec4396327db5e6d7c98645a73089 Mon Sep 17 00:00:00 2001 From: Charles Lepple Date: Thu, 6 Aug 2015 22:31:20 -0400 Subject: [PATCH 0004/1232] Remove some old compatibility information from the README --- README.adoc | 52 ++++------------------------------------------------ 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/README.adoc b/README.adoc index 1b44663d8e..33f61af264 100644 --- a/README.adoc +++ b/README.adoc @@ -476,62 +476,18 @@ The past stable trees were 1.0, 1.2, 1.4, 2.0, 2.2 and 2.4, with the latest stable tree designated 2.6. The development trees were 1.1, 1.3, 1.5, 2.1 and 2.3. As of the 2.4 release, there is no real development branch anymore since the code is available through a revision control -system (namely Subversion) and snapshots. +system (namely, Git) and snapshots. Major release jumps are mostly due to large changes to the features list. There have also been a number of architectural changes which may not be noticeable to most users, but which can impact developers. - Backwards and Forwards Compatibility ------------------------------------ -The old network code spans a range from about 0.41.1 when TCP support -was introduced up to the recent 1.4 series. It used variable names -like STATUS, UTILITY, and LOADPCT. Many of these names go back to the -earliest prototypes of this software from 1997. At that point there -was no way to know that so many drivers would come along and introduce -so many new variables and commands. The resulting mess grew out of -control over the years. - -During the 1.3 development cycle, all variables and instant commands -were renamed to fit into a tree-like structure. There are major groups, -like input, output and battery. Members of those groups have been -arranged to make sense - input.voltage and output.voltage compliment -each other. The old names were UTILITY and OUTVOLT. The benefits in -this change are obvious. - -The 1.4 clients can talk to either type of server, and can handle either -naming scheme. 1.4 servers have a compatibility mode where they can -answer queries for both names, even though the drivers are internally -using the new format. - -When 1.4 clients talk to 1.4 or 2.0 (or more recent) servers, they will -use the new names. - -Here's a table to make it easier to visualize: - -[options="header"] -|============================================= -| 4+| Server version -| *Client version* | 1.0 | 1.2 | 1.4 | 2.0+ -| 1.0 | yes | yes | yes | no -| 1.2 | yes | yes | yes | no -| 1.4 | yes | yes | yes | yes -| 2.0+ | no | no | yes | yes -|============================================= - -Version 2.0, and more recent, do not contain backwards compatibility for -the old protocol and variable/command names. As a result, 2.0 clients can't -talk to anything older than a 1.4 server. If you ask a 2.0 client to -fetch "STATUS", it will fail. You'll have to ask for "ups.status" -instead. - -Authors of separate monitoring programs should have used the 1.4 series -to write support for the new variables and command names. Client -software can easily support both versions as long as they like. If upsd -returns 'ERR UNKNOWN-COMMAND' to a GET request, you need to use REQ. - +The network protocol for the current version of NUT should be +backwards-compatible all the way back to version 1.4. A newer client should +fail gracefully when querying an older server. Support / Help / etc. --------------------- From fa209d32c970c873ed63c3e71bee9a948c60e06c Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 16:07:00 +0200 Subject: [PATCH 0005/1232] Make nutdrv_qx the 'generic device driver' for Q* protocols As the link was still pointing to the old -no longer generated- 'blazer' manpage, take the chance to reword the paragraph so that it points to the new nutdrv_qx driver. --- README.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index 33f61af264..155a8651e3 100644 --- a/README.adoc +++ b/README.adoc @@ -190,11 +190,11 @@ with incorrect scale factors. + See the linkman:usbhid-ups[8] man page for more information. -- The `blazer_ser` and `blazer_usb` drivers supports the Megatec / Q1 -protocol that is used in many brands (Blazer, Energy Sistem, Fenton -Technologies, Mustek and many others). +- The `nutdrv_qx` driver supports the Megatec / Q1 protocol that is used in +many brands (Blazer, Energy Sistem, Fenton Technologies, Mustek, Voltronic +Power and many others). + -See the linkman:blazer[8] man page for more information. +See the linkman:nutdrv_qx[8] man page for more information. - The `snmp-ups` driver handles various SNMP enabled devices, from many different manufacturers. In SNMP terms, `snmp-ups` is a manager, that From fb0d3403df35a8cd0f439a467747d7e933c3c4ba Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 16:36:47 +0200 Subject: [PATCH 0006/1232] Make links to docs/manpages work in both GitHub and generated docs Since GitHub doesn't allow custom macros, only use ours when generating docs, replacing their occurrences with attributes that produce links when on GitHub. This approach should work properly as long as we use them in contexts where attributes are evaluated and substituted before macros. Also, use a common attribute that points to the URL of the website. Reference: https://github.com/networkupstools/nut/pull/226 --- README.adoc | 68 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/README.adoc b/README.adoc index 155a8651e3..98e2d2c41a 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,48 @@ Network UPS Tools Overview =========================== +:website-url: http://www.networkupstools.org/ + +// Address links on GitHub vs docs +// (note: 'env-github' attribute is set on GitHub) +// - when generating docs: +ifndef::env-github[] +// * link to doc -> our macro +// syntax: {linkdoc}{ld-s}[] +// -> linkdoc:[] +:linkdoc: linkdoc: +:ld-s: +// * link to manpage -> our macro +:linkman_apcupsd-ups-8: linkman:apcupsd-ups[8] +:linkman_genericups-8: linkman:genericups[8] +:linkman_nutdrv_qx-8: linkman:nutdrv_qx[8] +:linkman_powerman-pdu-8: linkman:powerman-pdu[8] +:linkman_snmp-ups-8: linkman:snmp-ups[8] +:linkman_upsc-8: linkman:upsc[8] +:linkman_upsd-users-5: linkman:upsd.users[5] +:linkman_upsmon-8: linkman:upsmon[8] +:linkman_usbhid-ups-8: linkman:usbhid-ups[8] +endif::env-github[] +// - on GitHub: +ifdef::env-github[] +// * link to doc -> link +// syntax: {linkdoc}{ld-s}[] +// -> {website-url}docs/.chunked/index.html[] +:linkdoc: {website-url}docs/ +:ld-s: .chunked/index.html +// * link to manpage -> link +:man-url: {website-url}docs/man/ +:linkman_apcupsd-ups-8: {man-url}apcupsd-ups.html[apcupsd-ups(8)] +:linkman_genericups-8: {man-url}genericups.html[genericups(8)] +:linkman_nutdrv_qx-8: {man-url}nutdrv_qx.html[nutdrv_qx(8)] +:linkman_powerman-pdu-8: {man-url}powerman-pdu.html[powerman-pdu[8)] +:linkman_snmp-ups-8: {man-url}snmp-ups.html[snmp-ups(8)] +:linkman_upsc-8: {man-url}upsc.html[upsc(8)] +:linkman_upsd-users-5: {man-url}upsd.users.html[upsd.users[5)] +:linkman_upsmon-8: {man-url}upsmon.html[upsmon(8)] +:linkman_usbhid-ups-8: {man-url}usbhid-ups.html[usbhid-ups(8)] +endif::env-github[] + Description ----------- @@ -159,7 +201,7 @@ For example, it is available on Debian systems as: /usr/share/nut/driver.list -This table is also available link:http://www.networkupstools.org/stable-hcl.html[online]. +This table is also available link:{website-url}stable-hcl.html[online]. If your driver has vanished, see the link:FAQ.html[FAQ] and @@ -180,7 +222,7 @@ data about power and battery status. Advanced features like battery charge readings and such require a "smart" UPS and a driver which supports it. + -See the linkman:genericups[8] man page for more information. +See the {linkman_genericups-8} man page for more information. - The `usbhid-ups` driver attempts to communicate with USB HID Power Device Class (PDC) UPSes. These units generally implement the same basic protocol, @@ -188,32 +230,32 @@ with minor variations in the exact set of supported attributes. This driver also applies several correction factors when the UPS firmware reports values with incorrect scale factors. + -See the linkman:usbhid-ups[8] man page for more information. +See the {linkman_usbhid-ups-8} man page for more information. - The `nutdrv_qx` driver supports the Megatec / Q1 protocol that is used in many brands (Blazer, Energy Sistem, Fenton Technologies, Mustek, Voltronic Power and many others). + -See the linkman:nutdrv_qx[8] man page for more information. +See the {linkman_nutdrv_qx-8} man page for more information. - The `snmp-ups` driver handles various SNMP enabled devices, from many different manufacturers. In SNMP terms, `snmp-ups` is a manager, that monitors SNMP agents. + -See the linkman:snmp-ups[8] man page for more information. +See the {linkman_snmp-ups-8} man page for more information. - The `powerman-pdu` is a bridge to the PowerMan daemon, thus handling all PowerMan supported devices. The PowerMan project supports several serial and networked PDU, along with Blade and IPMI enabled servers. + -See the linkman:powerman-pdu[8] man page for more +See the {linkman_powerman-pdu-8} man page for more information. - The `apcupsd-ups` driver is a bridge to the Apcupsd daemon, thus handling all Apcupsd supported devices. The Apcupsd project supports many serial, USB and networked APC UPS. + -See the linkman:apcupsd-ups[8] man page for more information. +See the {linkman_apcupsd-ups-8} man page for more information. UPS Shutdowns ~~~~~~~~~~~~~ @@ -293,7 +335,7 @@ Additional Information More information on configuring upsmon can be found in these places: -- The linkman:upsmon[8] man page +- The {linkman_upsmon-8} man page - <> - <> chapter - The stock `upsmon.conf` that comes with the package @@ -332,7 +374,7 @@ If you are interested in writing a simple client that monitors `upsd`, the source code for `upsc` is a good way to learn about using the upsclient functions. -See the linkman:upsc[8] man page and +See the {linkman_upsc-8} man page and <> for more information. upslog @@ -371,7 +413,7 @@ On the other hand, one that doesn't support them won't print anything: ( nothing ) `upsrw` requires administrator powers to change settings in the hardware. -Refer to linkman:upsd.users[5] for information on defining +Refer to {linkman_upsd-users-5} for information on defining users in `upsd`. upscmd @@ -395,7 +437,7 @@ Use the -l command to list them, like this: `upscmd` requires administrator powers to start instant commands. To define users and passwords in `upsd`, see -linkman:upsd.users[5]. +{linkman_upsd-users-5}. CGI Programs @@ -501,8 +543,8 @@ Hacking / Development Info Additional documentation can be found in: -- the linkdoc:developer-guide[Developer Guide], -- the linkdoc:packager-guide[Packager Guide]. +- the {linkdoc}developer-guide{ld-s}[Developer Guide], +- the {linkdoc}packager-guide{ld-s}[Packager Guide]. Acknowledgements / Contributions From 3cfae1e071863403905fcfefe36ae177feecd2ed Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 17:06:37 +0200 Subject: [PATCH 0007/1232] Make cross references work in both GitHub and generated docs Substitute the shorthand '<< >>' syntax with attributes that conditionally expand to: - links on GitHub (references can point at most to a section of level docs/common.xsl's ), - xref macros when generating docs. In order to achieve the result, 'chunked' docs get now their pages named after IDs. So, update all the links that use the old auto-generated names. Reference: https://github.com/networkupstools/nut/pull/226 --- README.adoc | 36 ++++++++++++++++++++++++------------ docs/chunked.xsl | 1 + docs/download.txt | 2 +- docs/support.txt | 4 ++-- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/README.adoc b/README.adoc index 98e2d2c41a..c17ec1e506 100644 --- a/README.adoc +++ b/README.adoc @@ -7,6 +7,11 @@ Network UPS Tools Overview // (note: 'env-github' attribute is set on GitHub) // - when generating docs: ifndef::env-github[] +// * xref -> xref +// syntax: {xref}{x-s}[] +// -> xref:[] +:xref: xref: +:x-s: // * link to doc -> our macro // syntax: {linkdoc}{ld-s}[] // -> linkdoc:[] @@ -25,6 +30,13 @@ ifndef::env-github[] endif::env-github[] // - on GitHub: ifdef::env-github[] +// * xref -> link +// syntax: {xref}{x-s}[] +// In order for it to work, can reference at most a section of +// level docs/common.xsl's +// -> {website-url}docs/user-manual.chunked/.html[] +:xref: {website-url}docs/user-manual.chunked/ +:x-s: .html // * link to doc -> link // syntax: {linkdoc}{ld-s}[] // -> {website-url}docs/.chunked/index.html[] @@ -76,7 +88,7 @@ Installing ---------- If you are installing these programs for the first time, go read the -<<_installation_instructions,installation instructions>> +{xref}_installation_instructions{x-s}[installation instructions] to find out how to do that. This document contains more information on what all of this stuff does. @@ -85,7 +97,7 @@ Upgrading --------- When upgrading from an older version, always check the -<> to see what may have +{xref}Upgrading_notes{x-s}[upgrading notes] to see what may have changed. Compatibility issues and other changes will be listed there to ease the process. @@ -94,7 +106,7 @@ Configuring and using --------------------- Once NUT is installed, refer to the -<> for directions. +{xref}Configuration_notes{x-s}[configuration notes] for directions. Documentation @@ -195,7 +207,7 @@ feature, just add another line to your ups.conf section for that UPS: Hardware Compatibility List ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The <> is available in the source directory +The {xref}HCL{x-s}[Hardware Compatibility List] is available in the source directory ('nut-X.Y.Z/data/driver.list'), and is generally distributed with packages. For example, it is available on Debian systems as: @@ -205,7 +217,7 @@ This table is also available link:{website-url}stable-hcl.html[online]. If your driver has vanished, see the link:FAQ.html[FAQ] and -<>. +{xref}Upgrading_notes{x-s}[Upgrading notes]. Generic Device Drivers ~~~~~~~~~~~~~~~~~~~~~~ @@ -268,7 +280,7 @@ to die. Don't power off your computers unless they're ready for it: /usr/local/ups/sbin/upsdrvctl shutdown /usr/local/ups/sbin/upsdrvctl shutdown sparky -You should read the <> +You should read the {xref}UPS_shutdown{x-s}[Configuring automatic UPS shutdowns] chapter to learn more about when to use this feature. If called at the wrong time, you may cause data loss by turning off a system with a filesystem mounted read-write. @@ -278,7 +290,7 @@ Power distribution unit management NUT also provides an advanced support for power distribution units. -You should read the <> +You should read the {xref}Outlets_PDU_notes{x-s}[Configuring automatic UPS shutdowns] chapter to learn more about when to use this feature. Network Server @@ -336,8 +348,8 @@ Additional Information More information on configuring upsmon can be found in these places: - The {linkman_upsmon-8} man page -- <> -- <> chapter +- {xref}BigServers{x-s}[Typical setups for big servers] +- {xref}UPS_shutdown{x-s}[Configuring automatic UPS shutdowns] chapter - The stock `upsmon.conf` that comes with the package @@ -375,7 +387,7 @@ the source code for `upsc` is a good way to learn about using the upsclient functions. See the {linkman_upsc-8} man page and -<> for more information. +{xref}nut-names{x-s}[NUT command and variable naming scheme] for more information. upslog ~~~~~~ @@ -535,7 +547,7 @@ Support / Help / etc. --------------------- If you are in need of help, refer to the -<> in the user manual. +{xref}Support_Request{x-s}[Support instructions] in the user manual. Hacking / Development Info @@ -551,4 +563,4 @@ Acknowledgements / Contributions -------------------------------- The many people who have participated in creating and improving NUT are -listed in the user manual <>. +listed in the user manual {xref}Acknowledgements{x-s}[acknowledgements appendix]. diff --git a/docs/chunked.xsl b/docs/chunked.xsl index 7f09a80f28..05c2f66324 100644 --- a/docs/chunked.xsl +++ b/docs/chunked.xsl @@ -14,4 +14,5 @@ images/icons/ images/icons/ + diff --git a/docs/download.txt b/docs/download.txt index b92e4c530c..f855e09996 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -12,7 +12,7 @@ You should always use PGP/GPG to verify the signatures before using any source c You can use the ifdef::website[] -link:docs/user-manual.chunked/ar01s09.html#verifySourceSig[following procedure] +link:docs/user-manual.chunked/NUT_Security.html#verifySourceSig[following procedure] endif::website[] ifndef::website[] <>. diff --git a/docs/support.txt b/docs/support.txt index 9e6b6ebb24..0f1e9da1ee 100644 --- a/docs/support.txt +++ b/docs/support.txt @@ -86,12 +86,12 @@ Refer to the ifdef::website[] link:docs/developer-guide.chunked/index.html[NUT Developer Guide] for more information, and the chapter on how to -link:docs/developer-guide.chunked/ar01s03.html#_submitting_patches[submit patches]. +link:docs/developer-guide.chunked/developers.html#_submitting_patches[submit patches]. endif::website[] ifndef::website[] linkdoc:developer-guide[NUT Developer Guide] for more information, and the chapter on how to -link:../developer-guide.chunked/ar01s03.html#_submitting_patches[submit patches]. +link:../developer-guide.chunked/developers.html#_submitting_patches[submit patches]. endif::website[] From e957c9f292ac1f8053d02055eac03768bd1077a3 Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 17:47:42 +0200 Subject: [PATCH 0008/1232] Remove a couple of end-of-line spaces --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index c17ec1e506..c0e3da9e61 100644 --- a/README.adoc +++ b/README.adoc @@ -156,7 +156,7 @@ This package is broken down into several categories: - *clients* - They talk to upsd and do things with the status data. - *cgi-bin* - Special class of clients that you can use with your web server. - *scripts* - Contains various scripts, like the Perl and Python binding, -integration bits and applications. +integration bits and applications. Drivers ------- @@ -291,7 +291,7 @@ Power distribution unit management NUT also provides an advanced support for power distribution units. You should read the {xref}Outlets_PDU_notes{x-s}[Configuring automatic UPS shutdowns] -chapter to learn more about when to use this feature. +chapter to learn more about when to use this feature. Network Server -------------- From 77865e57d9031416a6abc2eb8691790fb1c2ca26 Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 20:21:22 +0200 Subject: [PATCH 0009/1232] Make AsciiDoc xref macros work properly in DocBook-generated docs AsciiDoc <= ~8.6.9 tests the wrong attribute and, as a consequence of that, it produces both and . To workaround this issue, implement the xref macro by ourselves. --- docs/asciidoc.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/asciidoc.conf b/docs/asciidoc.conf index fedf952a37..2b8dcc2328 100644 --- a/docs/asciidoc.conf +++ b/docs/asciidoc.conf @@ -29,6 +29,12 @@ (?su)[\\]?(?Plinkdoc):(?P\S*?)\[(?P.*?)\]= ifdef::basebackend-docbook[] +# AsciiDoc <= ~8.6.9 tests the wrong attribute and, as a consequence of that, it produces both and . +# To workaround this issue, implement the xref macro by ourselves. +[xref-inlinemacro] +{0} +{0%} + ifdef::xhtml11_format[] [linkman-inlinemacro] {target}{0?({0})} From 64e582a923bb932beffd3672f55f24cc02a60885 Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 21:52:11 +0200 Subject: [PATCH 0010/1232] Update some URLs and make them clickable --- README.adoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index c0e3da9e61..ec015efa63 100644 --- a/README.adoc +++ b/README.adoc @@ -466,14 +466,13 @@ get it and install it before continuing. You can get the source here: - http://www.libgd.org/ +- http://www.libgd.org/ In the event that you need libpng or zlib in order to compile gd, they can be found at these URLs: - http://www.libpng.org/pub/png/pngcode.html - - http://www.gzip.org/zlib/ +- http://www.libpng.org/pub/png/pngcode.html +- http://www.zlib.net/ Access Restrictions From e64f9b0894a49cd81251db9a8fa36441b4e6f96a Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Mon, 24 Aug 2015 22:10:31 +0200 Subject: [PATCH 0011/1232] docs: add 'linksingledoc' AsciiDoc macro Add a new 'linksingledoc' AsciiDoc macro which guarantees that, when chunked HTML is generated, the link always points to a non-chunked file. --- README.adoc | 12 +++++++++++- docs/asciidoc.conf | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index ec015efa63..0aaca64181 100644 --- a/README.adoc +++ b/README.adoc @@ -17,6 +17,11 @@ ifndef::env-github[] // -> linkdoc:[] :linkdoc: linkdoc: :ld-s: +// * link to single doc -> our macro +// syntax: {linksingledoc}{lsd-s}[] +// -> linksingledoc:[] +:linksingledoc: linksingledoc: +:lsd-s: // * link to manpage -> our macro :linkman_apcupsd-ups-8: linkman:apcupsd-ups[8] :linkman_genericups-8: linkman:genericups[8] @@ -42,6 +47,11 @@ ifdef::env-github[] // -> {website-url}docs/.chunked/index.html[] :linkdoc: {website-url}docs/ :ld-s: .chunked/index.html +// * link to single doc -> link +// syntax: {linksingledoc}{lsd-s}[] +// -> {website-url}docs/.html[] +:linksingledoc: {website-url}docs/ +:lsd-s: .html // * link to manpage -> link :man-url: {website-url}docs/man/ :linkman_apcupsd-ups-8: {man-url}apcupsd-ups.html[apcupsd-ups(8)] @@ -216,7 +226,7 @@ For example, it is available on Debian systems as: This table is also available link:{website-url}stable-hcl.html[online]. -If your driver has vanished, see the link:FAQ.html[FAQ] and +If your driver has vanished, see the {linksingledoc}FAQ{lsd-s}[FAQ] and {xref}Upgrading_notes{x-s}[Upgrading notes]. Generic Device Drivers diff --git a/docs/asciidoc.conf b/docs/asciidoc.conf index 2b8dcc2328..a5549871a2 100644 --- a/docs/asciidoc.conf +++ b/docs/asciidoc.conf @@ -1,4 +1,4 @@ -## NUT macros: linkman, linkdoc +## NUT macros: linkman, linkdoc, linksingledoc # # Usage: linkman:command[manpage-section] # This macro allows to handle variable manpage location, depending on the @@ -16,6 +16,9 @@ # Usage: linkdoc:document[display title,[anchor]] # This macro allows to handle variable NUT documentation location, depending # on the document type +# Usage: linksingledoc:document[display title,[anchor]] +# Just like linkdoc macro, but, when chunked HTML is generated, this one always +# points to a non-chunked file # # Note, {1} is the display title, {2} is the optional anchor name, # {0} is the whole set of args ({1}...{n}) and {target} is the @@ -23,10 +26,12 @@ # Example: # linkdoc:user-manual[user manual,NUT_Security] # linkdoc:developer-guide[developer guide,_status_data] +# linksingledoc:FAQ[shopping tips,_which_ups_should_i_buy] [macros] (?su)[\\]?(?Plinkman):(?P\S*?)\[(?P.*?)\]= (?su)[\\]?(?Plinkdoc):(?P\S*?)\[(?P.*?)\]= +(?su)[\\]?(?Plinksingledoc):(?P\S*?)\[(?P.*?)\]= ifdef::basebackend-docbook[] # AsciiDoc <= ~8.6.9 tests the wrong attribute and, as a consequence of that, it produces both and . @@ -40,6 +45,8 @@ ifdef::xhtml11_format[] {target}{0?({0})} [linkdoc-inlinemacro] {1} +[linksingledoc-inlinemacro] +{1} endif::xhtml11_format[] # FIXME: linkdoc does not support 'anchor' @@ -48,14 +55,18 @@ ifdef::chunked_format[] {target}{0?({0})} [linkdoc-inlinemacro] {1} +[linksingledoc-inlinemacro] +{1} endif::chunked_format[] # PDF output points online versions -# FIXME: linkdoc does not support 'anchor' +# FIXME: linkdoc and linksingledoc don't support 'anchor' ifdef::pdf_format[] [linkman-inlinemacro] {target}{0?({0})} [linkdoc-inlinemacro] {1} +[linksingledoc-inlinemacro] +{1} endif::pdf_format[] endif::basebackend-docbook[] From 8e88bf0ea6327188f7f3b4501f35bde8958c2bef Mon Sep 17 00:00:00 2001 From: Daniele Pezzini Date: Tue, 25 Aug 2015 00:34:38 +0200 Subject: [PATCH 0012/1232] docs: add 'linkman2' AsciiDoc macro Add a new 'linkman2' AsciiDoc macro to support different names for the manpage and the command shown. This is also needed to properly display links to manpages in both GitHub and generated docs without defining an attribute for each manpage. Reference: https://github.com/networkupstools/nut/pull/226 --- README.adoc | 70 +++++++++++++++++++----------------------- docs/asciidoc.conf | 21 +++++++++++-- docs/man/asciidoc.conf | 16 ++++++++-- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/README.adoc b/README.adoc index 0aaca64181..a588129c8a 100644 --- a/README.adoc +++ b/README.adoc @@ -10,28 +10,25 @@ ifndef::env-github[] // * xref -> xref // syntax: {xref}{x-s}[] // -> xref:[] -:xref: xref: +:xref: xref: :x-s: // * link to doc -> our macro // syntax: {linkdoc}{ld-s}[] // -> linkdoc:[] -:linkdoc: linkdoc: +:linkdoc: linkdoc: :ld-s: // * link to single doc -> our macro // syntax: {linksingledoc}{lsd-s}[] // -> linksingledoc:[] -:linksingledoc: linksingledoc: +:linksingledoc: linksingledoc: :lsd-s: // * link to manpage -> our macro -:linkman_apcupsd-ups-8: linkman:apcupsd-ups[8] -:linkman_genericups-8: linkman:genericups[8] -:linkman_nutdrv_qx-8: linkman:nutdrv_qx[8] -:linkman_powerman-pdu-8: linkman:powerman-pdu[8] -:linkman_snmp-ups-8: linkman:snmp-ups[8] -:linkman_upsc-8: linkman:upsc[8] -:linkman_upsd-users-5: linkman:upsd.users[5] -:linkman_upsmon-8: linkman:upsmon[8] -:linkman_usbhid-ups-8: linkman:usbhid-ups[8] +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// -> linkman2:[,] +:linkman2: linkman2: +:lm-s: [ +:lm-c: , +:lm-e: ] endif::env-github[] // - on GitHub: ifdef::env-github[] @@ -40,29 +37,26 @@ ifdef::env-github[] // In order for it to work, can reference at most a section of // level docs/common.xsl's // -> {website-url}docs/user-manual.chunked/.html[] -:xref: {website-url}docs/user-manual.chunked/ -:x-s: .html +:xref: {website-url}docs/user-manual.chunked/ +:x-s: .html // * link to doc -> link // syntax: {linkdoc}{ld-s}[] // -> {website-url}docs/.chunked/index.html[] -:linkdoc: {website-url}docs/ -:ld-s: .chunked/index.html +:linkdoc: {website-url}docs/ +:ld-s: .chunked/index.html // * link to single doc -> link // syntax: {linksingledoc}{lsd-s}[] // -> {website-url}docs/.html[] -:linksingledoc: {website-url}docs/ -:lsd-s: .html +:linksingledoc: {website-url}docs/ +:lsd-s: .html // * link to manpage -> link -:man-url: {website-url}docs/man/ -:linkman_apcupsd-ups-8: {man-url}apcupsd-ups.html[apcupsd-ups(8)] -:linkman_genericups-8: {man-url}genericups.html[genericups(8)] -:linkman_nutdrv_qx-8: {man-url}nutdrv_qx.html[nutdrv_qx(8)] -:linkman_powerman-pdu-8: {man-url}powerman-pdu.html[powerman-pdu[8)] -:linkman_snmp-ups-8: {man-url}snmp-ups.html[snmp-ups(8)] -:linkman_upsc-8: {man-url}upsc.html[upsc(8)] -:linkman_upsd-users-5: {man-url}upsd.users.html[upsd.users[5)] -:linkman_upsmon-8: {man-url}upsmon.html[upsmon(8)] -:linkman_usbhid-ups-8: {man-url}usbhid-ups.html[usbhid-ups(8)] +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// All the fields are mandatory. +// -> {website-url}docs/man/.html[()] +:linkman2: {website-url}docs/man/ +:lm-s: .html[ +:lm-c: ( +:lm-e: )] endif::env-github[] Description @@ -244,7 +238,7 @@ data about power and battery status. Advanced features like battery charge readings and such require a "smart" UPS and a driver which supports it. + -See the {linkman_genericups-8} man page for more information. +See the {linkman2}genericups{lm-s}genericups{lm-c}8{lm-e} man page for more information. - The `usbhid-ups` driver attempts to communicate with USB HID Power Device Class (PDC) UPSes. These units generally implement the same basic protocol, @@ -252,32 +246,32 @@ with minor variations in the exact set of supported attributes. This driver also applies several correction factors when the UPS firmware reports values with incorrect scale factors. + -See the {linkman_usbhid-ups-8} man page for more information. +See the {linkman2}usbhid-ups{lm-s}usbhid-ups{lm-c}8{lm-e} man page for more information. - The `nutdrv_qx` driver supports the Megatec / Q1 protocol that is used in many brands (Blazer, Energy Sistem, Fenton Technologies, Mustek, Voltronic Power and many others). + -See the {linkman_nutdrv_qx-8} man page for more information. +See the {linkman2}nutdrv_qx{lm-s}nutdrv_qx{lm-c}8{lm-e} man page for more information. - The `snmp-ups` driver handles various SNMP enabled devices, from many different manufacturers. In SNMP terms, `snmp-ups` is a manager, that monitors SNMP agents. + -See the {linkman_snmp-ups-8} man page for more information. +See the {linkman2}snmp-ups{lm-s}snmp-ups{lm-c}8{lm-e} man page for more information. - The `powerman-pdu` is a bridge to the PowerMan daemon, thus handling all PowerMan supported devices. The PowerMan project supports several serial and networked PDU, along with Blade and IPMI enabled servers. + -See the {linkman_powerman-pdu-8} man page for more +See the {linkman2}powerman-pdu{lm-s}powerman-pdu{lm-c}8{lm-e} man page for more information. - The `apcupsd-ups` driver is a bridge to the Apcupsd daemon, thus handling all Apcupsd supported devices. The Apcupsd project supports many serial, USB and networked APC UPS. + -See the {linkman_apcupsd-ups-8} man page for more information. +See the {linkman2}apcupsd-ups{lm-s}apcupsd-ups{lm-c}8{lm-e} man page for more information. UPS Shutdowns ~~~~~~~~~~~~~ @@ -357,7 +351,7 @@ Additional Information More information on configuring upsmon can be found in these places: -- The {linkman_upsmon-8} man page +- The {linkman2}upsmon{lm-s}upsmon{lm-c}8{lm-e} man page - {xref}BigServers{x-s}[Typical setups for big servers] - {xref}UPS_shutdown{x-s}[Configuring automatic UPS shutdowns] chapter - The stock `upsmon.conf` that comes with the package @@ -396,7 +390,7 @@ If you are interested in writing a simple client that monitors `upsd`, the source code for `upsc` is a good way to learn about using the upsclient functions. -See the {linkman_upsc-8} man page and +See the {linkman2}upsc{lm-s}upsc{lm-c}8{lm-e} man page and {xref}nut-names{x-s}[NUT command and variable naming scheme] for more information. upslog @@ -435,7 +429,7 @@ On the other hand, one that doesn't support them won't print anything: ( nothing ) `upsrw` requires administrator powers to change settings in the hardware. -Refer to {linkman_upsd-users-5} for information on defining +Refer to {linkman2}upsd.users{lm-s}upsd.users{lm-c}5{lm-e} for information on defining users in `upsd`. upscmd @@ -459,7 +453,7 @@ Use the -l command to list them, like this: `upscmd` requires administrator powers to start instant commands. To define users and passwords in `upsd`, see -{linkman_upsd-users-5}. +{linkman2}upsd.users{lm-s}upsd.users{lm-c}5{lm-e}. CGI Programs diff --git a/docs/asciidoc.conf b/docs/asciidoc.conf index a5549871a2..6de07fd893 100644 --- a/docs/asciidoc.conf +++ b/docs/asciidoc.conf @@ -1,12 +1,20 @@ -## NUT macros: linkman, linkdoc, linksingledoc +## NUT macros: linkman, linkman2, linkdoc, linksingledoc # # Usage: linkman:command[manpage-section] # This macro allows to handle variable manpage location, depending on the # document type +# Usage: linkman2:command-page[displayed-command,manpage-section] +# Just like linkman macro, but supports different names for the page and the +# command shown. # -# Note, {0} is the manpage section, while {target} is the command. +# Note: +# - in linkman, {0} is the manpage section, while {target} is the command. +# - in linkman2, {0} is the whole list of attributes, {1} is the command to be +# shown, {2} is the manpage section, while {target} is the command page. # -# Example: linkman:ups.conf[5] +# Example: +# linkman:ups.conf[5] +# linkman2:ups_conf[ups.conf,5] # # Show NUT link as: (
); if section is defined, else just show # the command. @@ -30,6 +38,7 @@ [macros] (?su)[\\]?(?Plinkman):(?P\S*?)\[(?P.*?)\]= +(?su)[\\]?(?Plinkman2):(?P\S*?)\[(?P.*?)\]= (?su)[\\]?(?Plinkdoc):(?P\S*?)\[(?P.*?)\]= (?su)[\\]?(?Plinksingledoc):(?P\S*?)\[(?P.*?)\]= @@ -43,6 +52,8 @@ ifdef::basebackend-docbook[] ifdef::xhtml11_format[] [linkman-inlinemacro] {target}{0?({0})} +[linkman2-inlinemacro] +{1={target}}{2?({2})} [linkdoc-inlinemacro] {1} [linksingledoc-inlinemacro] @@ -53,6 +64,8 @@ endif::xhtml11_format[] ifdef::chunked_format[] [linkman-inlinemacro] {target}{0?({0})} +[linkman2-inlinemacro] +{1={target}}{2?({2})} [linkdoc-inlinemacro] {1} [linksingledoc-inlinemacro] @@ -64,6 +77,8 @@ endif::chunked_format[] ifdef::pdf_format[] [linkman-inlinemacro] {target}{0?({0})} +[linkman2-inlinemacro] +{1={target}}{2?({2})} [linkdoc-inlinemacro] {1} [linksingledoc-inlinemacro] diff --git a/docs/man/asciidoc.conf b/docs/man/asciidoc.conf index 9b4533d497..a2761d0db0 100644 --- a/docs/man/asciidoc.conf +++ b/docs/man/asciidoc.conf @@ -1,15 +1,20 @@ ## Borrowed from 'linkgit' in the Git distribution. -## linkman: macro +## linkman, linkman2 macros # # Usage: linkman:command[manpage-section] +# Usage: linkman2:command-page[displayed-command,manpage-section] # -# Note, {0} is the manpage section, while {target} is the command. +# Note: +# - in linkman, {0} is the manpage section, while {target} is the command. +# - in linkman2, {0} is the whole list of attributes, {1} is the command to be +# shown, {2} is the manpage section, while {target} is the command page. # # Show NUT link as: (
); if section is defined, else just show # the command. [macros] (?su)[\\]?(?Plinkman):(?P\S*?)\[(?P.*?)\]= +(?su)[\\]?(?Plinkman2):(?P\S*?)\[(?P.*?)\]= ifdef::backend-docbook[] [linkman-inlinemacro] @@ -17,11 +22,18 @@ ifdef::backend-docbook[] {0#} {0#{target}{0}} {0#} +[linkman2-inlinemacro] +{2%{1={target}}} +{2#} +{2#{1={target}}{2}} +{2#} endif::backend-docbook[] ifdef::backend-xhtml11[] [linkman-inlinemacro] {target}{0?({0})} +[linkman2-inlinemacro] +{1={target}}{2?({2})} # Override HTML footer, to include NUT version [footer-text] From f6ca71b5dffacba58df9451875d73c4556638a93 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Jun 2023 17:09:37 +0200 Subject: [PATCH 0013/1232] configure.ac, include/Makefile.am: constrain use of "git describe" to release tags [#1949, networkupstools/nut-website#35, networkupstools/nut-website#34] --- configure.ac | 2 +- include/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 80ad237742..671cd2a11d 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ. (command -v git >/dev/null 2>/dev/null) \ -&& NUT_SOURCE_GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +&& NUT_SOURCE_GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" dnl Note: except for experiments, do not pass this into config.h - use diff --git a/include/Makefile.am b/include/Makefile.am index 38e1c69c45..78e65db31b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -18,7 +18,7 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # (for builds not made from the tagged commit in a Git workspace) nut_version.h: @FORCE_NUT_VERSION@ - @GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ + @GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ { echo '/* Autogenerated file. Do not change. */' ; \ echo '/* This file was generated by "make". */' ; \ if [ -z "$$GITREV" ]; then \ From 27ac22d07067dead64dd2843a4a366bb38d604b9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 4 Apr 2022 11:04:28 +0000 Subject: [PATCH 0014/1232] configure.ac: fall back to exclude-only filter of "git describe" tags if autoconf/m4/shell messes up the "match" ones --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 671cd2a11d..38e2bfde3c 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ. (command -v git >/dev/null 2>/dev/null) \ -&& NUT_SOURCE_GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" dnl Note: except for experiments, do not pass this into config.h - use From ccde6a7ea9e36a3530cc48172cd993f106c0a2c9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 4 Apr 2022 11:04:28 +0000 Subject: [PATCH 0015/1232] configure.ac, include/Makefile.am: avoid picking "vX.Y.Z-signed" tags, only "vX.Y.Z" name denotes the release officially --- configure.ac | 2 +- include/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 38e2bfde3c..adafce4b7e 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ. (command -v git >/dev/null 2>/dev/null) \ -&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" dnl Note: except for experiments, do not pass this into config.h - use diff --git a/include/Makefile.am b/include/Makefile.am index 78e65db31b..646abc8e15 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -18,7 +18,7 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # (for builds not made from the tagged commit in a Git workspace) nut_version.h: @FORCE_NUT_VERSION@ - @GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]-signed' --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ + @GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ { echo '/* Autogenerated file. Do not change. */' ; \ echo '/* This file was generated by "make". */' ; \ if [ -z "$$GITREV" ]; then \ From e5135f03d66716ee721ffeb2fe6e20dfe33f289e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 4 Apr 2022 11:04:28 +0000 Subject: [PATCH 0016/1232] configure.ac, include/Makefile.am: avoid picking "vX.Y.Z-signed" tags more actively --- configure.ac | 2 +- include/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index adafce4b7e..22525dfb98 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ. (command -v git >/dev/null 2>/dev/null) \ -&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" dnl Note: except for experiments, do not pass this into config.h - use diff --git a/include/Makefile.am b/include/Makefile.am index 646abc8e15..e9bcdd88f6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -18,7 +18,7 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # (for builds not made from the tagged commit in a Git workspace) nut_version.h: @FORCE_NUT_VERSION@ - @GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ + @GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \ { echo '/* Autogenerated file. Do not change. */' ; \ echo '/* This file was generated by "make". */' ; \ if [ -z "$$GITREV" ]; then \ From 1b37df969616351dd36adfd1dd7085593e3a8225 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 12 Sep 2022 10:49:14 +0200 Subject: [PATCH 0017/1232] drivers/apc-hid.c, NEWS, 95-upower-hid.hwdb: Support VID:PID = 0x051d:0x0004 [#1429] --- NEWS | 1 + drivers/apc-hid.c | 6 +++++- scripts/upower/95-upower-hid.hwdb | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f5fd4ccfde..922591af3f 100644 --- a/NEWS +++ b/NEWS @@ -67,6 +67,7 @@ https://github.com/networkupstools/nut/milestone/8 * cps-hid subdriver now applies same report descriptor fixing logic to devices with ProductID 0x0601 as done earlier for 0x0501, to get the correct output voltage data [#1497] + * apc-hid subdriver now also supports ProductID 0x0004 [#1429] * the `usbhid-ups` driver should now reconnect if `libusb` returned a memory allocation error [#1422] (seen as "Can't retrieve Report 0a: Resource temporarily unavailable"), which can cause practical problems diff --git a/drivers/apc-hid.c b/drivers/apc-hid.c index 5f806947be..3fa0894c2d 100644 --- a/drivers/apc-hid.c +++ b/drivers/apc-hid.c @@ -32,7 +32,7 @@ #include "apc-hid.h" #include "usb-common.h" -#define APC_HID_VERSION "APC HID 0.99" +#define APC_HID_VERSION "APC HID 0.100" /* APC */ #define APC_VENDORID 0x051d @@ -94,6 +94,10 @@ static usb_device_id_t apc_usb_device_table[] = { { USB_DEVICE(APC_VENDORID, 0x0002), general_apc_check }, /* various 5G models */ { USB_DEVICE(APC_VENDORID, 0x0003), disable_interrupt_pipe }, + /* APC Smart UPS 1000 with latest firmware 04.3 + * seems to have bumped the productid from 3 to 4 + * See https://github.com/networkupstools/nut/issues/1429 */ + { USB_DEVICE(APC_VENDORID, 0x0004), disable_interrupt_pipe }, /* Terminating entry */ { 0, 0, NULL } diff --git a/scripts/upower/95-upower-hid.hwdb b/scripts/upower/95-upower-hid.hwdb index b0b7fbfb8e..c5f0bdacdb 100644 --- a/scripts/upower/95-upower-hid.hwdb +++ b/scripts/upower/95-upower-hid.hwdb @@ -70,6 +70,7 @@ usb:v050Dp1100* usb:v051Dp0000* usb:v051Dp0002* usb:v051Dp0003* +usb:v051Dp0004* UPOWER_BATTERY_TYPE=ups UPOWER_VENDOR=APC From 70ef5f6380ac6a4cccd092499d2f57382921f095 Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Mon, 10 Oct 2022 16:54:57 +0200 Subject: [PATCH 0018/1232] Add SNMP apc easy pdu support --- drivers/Makefile.am | 4 +- drivers/apc-epdu-mib.c | 221 +++++++++++++++++++++++++++++++++++++++++ drivers/apc-epdu-mib.h | 29 ++++++ drivers/snmp-ups.c | 4 +- 4 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 drivers/apc-epdu-mib.c create mode 100644 drivers/apc-epdu-mib.h diff --git a/drivers/Makefile.am b/drivers/Makefile.am index bd40e63f4b..f689bd075a 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -231,7 +231,7 @@ mge_shut_LDADD = $(LDADD) -lm # Please keep the MIB table below sorted roughly alphabetically (incidentally # by vendor too) to ease maintenance and codebase fork resynchronisations snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ - apc-mib.c apc-pdu-mib.c \ + apc-mib.c apc-pdu-mib.c apc-epdu-mib.c \ baytech-mib.c bestpower-mib.c \ compaq-mib.c cyberpower-mib.c \ delta_ups-mib.c \ @@ -339,7 +339,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h nutdrv_qx_hunnox.h \ nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h nutdrv_qx_zinto.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 \ - apc-pdu-mib.h ever-hid.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h eaton-pdu-marlin-helpers.h \ + apc-pdu-mib.h apc-epdu-mib.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 legrand-hid.h \ hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h diff --git a/drivers/apc-epdu-mib.c b/drivers/apc-epdu-mib.c new file mode 100644 index 0000000000..db8f9ee5a6 --- /dev/null +++ b/drivers/apc-epdu-mib.c @@ -0,0 +1,221 @@ +/* apc-epdu-mib.c - subdriver to monitor apc SNMP easy pdu with NUT + * + * Copyright (C) + * 2011 - 2022 Eric Clappier + * + * Note: this subdriver was initially generated as a "stub" by the + * gen-snmp-subdriver script. It must be customized! + * + * 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 "apc-epdu-mib.h" + +#define APC_EPDU_MIB_VERSION "0.1" + +#define APC_EPDU_MIB_SYSOID ".1.3.6.1.4.1.318.1.3.4.9" + +static info_lkp_t apc_epdu_sw_outlet_status_info[] = { + { 1, "off", NULL, NULL }, + { 2, "on", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t apc_epdu_sw_outlet_switchability_info[] = { + { 1, "yes", NULL, NULL }, + { 2, "yes", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +/* POWERNET-MIB Snmp2NUT lookup table */ +static snmp_info_t apc_epdu_mib[] = { + + /* Device page */ + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* ePDUDeviceStatusModelNumber.1 = STRING: "EPDU1016M" */ + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.2.1.1.4.1", "Easy ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "device.contact", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_STALE | SU_FLAG_OK, NULL }, + { "device.description", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.5.0", NULL, SU_FLAG_STALE | SU_FLAG_OK, NULL }, + { "device.location", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_STALE | SU_FLAG_OK, NULL }, + /* FIXME: to be RFC'ed */ + { "device.uptime", 0, 1, ".1.3.6.1.2.1.1.3.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUDeviceStatusSerialNumber.1 = STRING: "506255604729" */ + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, " .1.3.6.1.4.1.318.1.1.30.2.1.1.5.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* ePDUDeviceStatusModelNumber.1 = STRING: "EPDU1016M" */ + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.2.1.1.4.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* ePDUDeviceStatusVersion.1 = STRING: "Ver16.10" */ + { "device.version", ST_FLAG_STRING, SU_INFOSIZE, " .1.3.6.1.4.1.318.1.1.30.2.1.1.3.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + + /* Input */ + /* ePDUDeviceStatusActivePower.1 = INTEGER: 785 */ + { "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* FIXME: Take first phase for global */ + /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ + { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseTableSize = INTEGER: 1 */ + { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.30.3.0", NULL, SU_FLAG_OK, NULL }, + /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ + { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusVoltage.2 = INTEGER: 2304 */ + { "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusVoltage.3 = INTEGER: 2304 */ + { "input.L3-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusCurrent.1 = INTEGER: 355 */ + { "input.L1.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusCurrent.2 = INTEGER: 355 */ + { "input.L2.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusCurrent.3 = INTEGER: 355 */ + { "input.L3.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusActivePower.1 = INTEGER: 785 */ + { "input.L1.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusActivePower.2 = INTEGER: 785 */ + { "input.L2.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + /* ePDUPhaseStatusActivePower.3 = INTEGER: 785 */ + { "input.L3.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + + /* Outlets */ + /* ePDUOutletTableSize.0 = INTEGER: 1 */ + { "outlet.count", 0, 1, ".1.3.6.1.4.1.318.1.1.30.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* ePDUOutletStatusIndex.%i = INTEGER: 1 */ + { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + /* ePDUOutletStatusNumber.%i = INTEGER: 1 */ + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.3.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + /* ePDUOutletStatusState.%i = INTEGER: off(1) */ + { "outlet.%i.status", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, &apc_epdu_sw_outlet_status_info[0] }, + /* Also use this OID to determine switchability ; its presence means "yes" */ + /* ePDUOutletStatusState.%i = INTEGER: off(1) */ + { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", "yes", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_epdu_sw_outlet_switchability_info[0] }, + +#if 0 /* keep following scan for future development */ + /* iso.3.6.1.4.1.318.1.1.30.1.0 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.1.0", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.3.1 = STRING: "Ver16.10" */ + { "unmapped.iso", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.2.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.4.1 = STRING: "EPDU1016M" */ + { "unmapped.iso", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.2.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.5.1 = STRING: "506255604717" */ + { "unmapped.iso", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.2.1.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.6.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.7.1 = INTEGER: 785 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.8.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.9.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.10.1 = INTEGER: 965 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.11.1 = INTEGER: 9114157 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.11.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.1.1.12.1 = INTEGER: 49988 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.12.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.2.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.2.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.2.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.2.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.2.1.3.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.2.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.2.1.4.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.2.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.2.2.1.5.1 = INTEGER: 2 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.2.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.3.0 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.3.0", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.3.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.4.1 = INTEGER: 3000 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.5.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.6.1 = INTEGER: 3200 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.1.1.7.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.1.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.3.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.4.1 = INTEGER: 2304 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.5.1 = INTEGER: 353 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.6.1 = INTEGER: 785 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.7.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.8.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.9.1 = INTEGER: 965 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.4.2.1.10.1 = INTEGER: 9114157 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.5.0 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.5.0", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.1.1.1.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.1.1.2.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.1.1.3.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.1.1.4.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.2.1.1.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.2.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.2.1.2.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.2.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.2.1.3.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.2.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.6.2.1.4.1 = INTEGER: -1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.2.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.7.0 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.7.0", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.3.1 = INTEGER: 900 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.4.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.5.1 = INTEGER: 900 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.1.1.6.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.2.1.1.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.2.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.2.1.2.1 = INTEGER: 1 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.2.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.2.1.3.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.2.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* iso.3.6.1.4.1.318.1.1.30.8.2.1.4.1 = INTEGER: 0 */ + { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.8.2.1.4.1", NULL, SU_FLAG_OK, NULL }, +#endif + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +}; + +mib2nut_info_t apc_pdu_epdu = { "apc", APC_EPDU_MIB_VERSION, NULL, NULL, apc_epdu_mib, APC_EPDU_MIB_SYSOID, NULL }; diff --git a/drivers/apc-epdu-mib.h b/drivers/apc-epdu-mib.h new file mode 100644 index 0000000000..168858ac2c --- /dev/null +++ b/drivers/apc-epdu-mib.h @@ -0,0 +1,29 @@ +/* apc-epdu-mib.h - subdriver to monitor apc SNMP easy pdu with NUT + * + * Copyright (C) + * 2011 - 2022 Eric Clappier + * + * 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 APC_EPDU_MIB_H +#define APC_EPDU_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t apc_pdu_epdu; + +#endif /* APC_EPDU_MIB_H */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 8d96742d8b..791fd123fd 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -63,6 +63,7 @@ #include "eaton-ats16-nm2-mib.h" #include "apc-ats-mib.h" #include "apc-pdu-mib.h" +#include "apc-epdu-mib.h" #include "eaton-ats30-mib.h" #include "emerson-avocent-pdu-mib.h" #include "hpe-pdu-mib.h" @@ -94,6 +95,7 @@ static mib2nut_info_t *mib2nut[] = { &apc_pdu_rpdu, /* This struct comes from : apc-pdu-mib.c */ &apc_pdu_rpdu2, /* This struct comes from : apc-pdu-mib.c */ &apc_pdu_msp, /* This struct comes from : apc-pdu-mib.c */ + &apc_pdu_epdu, /* This struct comes from : apc-epdu-mib.c */ &apc, /* This struct comes from : apc-mib.c */ &baytech, /* This struct comes from : baytech-mib.c */ &bestpower, /* This struct comes from : bestpower-mib.c */ @@ -166,7 +168,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.22" +#define DRIVER_VERSION "1.23" /* driver description structure */ upsdrv_info_t upsdrv_info = { From 4b950cd7ce4cbe70fb3df7b69b6a710be1175093 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 12 Oct 2022 15:17:25 +0200 Subject: [PATCH 0019/1232] NEWS: apc-epdu-mib added for NUT v2.8.1 --- NEWS | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index a18b3dcf1b..a57558c191 100644 --- a/NEWS +++ b/NEWS @@ -95,8 +95,10 @@ https://github.com/networkupstools/nut/milestone/8 Linux/illumos/FreeBSD/OpenBSD/... on dedicated NUT CI farm on Fosshost, and MacOS on CircleCI [#1552] - - snmp-ups IETF MIB mapping updated for data points where negative readings - are invalid [#1558] + - snmp-ups updates: + * IETF MIB mapping updated for data points where negative readings + are invalid [#1558] + * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] From 9148bfc0abe315113e20b5ed2af64a3e8ad5d7d0 Mon Sep 17 00:00:00 2001 From: zakx Date: Wed, 12 Oct 2022 15:56:02 +0000 Subject: [PATCH 0020/1232] Documentation update regarding Network-M2 card The Eaton Gigabit Network Card (Network-M2) is already well-supported by the powerware driver. This patch updates the documentation to reflect this. --- AUTHORS | 4 ++++ data/driver.list.in | 1 + docs/man/snmp-ups.txt | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index c179b0c55f..75398df85e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -174,3 +174,7 @@ D: Author of bcmxcp driver, 3-phase work. N: Giuseppe Corbelli E: giuseppe.corbelli@copanitalia.com D: Author of asem driver + +N: zakx +E: zakx@zakx.de +D: Updating device support docs after unneccessarily writing a redundant driver first diff --git a/data/driver.list.in b/data/driver.list.in index e6e72c0c65..f70250b469 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -371,6 +371,7 @@ "Eaton" "ups" "5" "various models (SNMP mode)" "NMC Minislot (ref 66102)" "snmp-ups (experimental)" "Eaton" "ups" "5" "various models (XML/HTTP mode)" "SNMP/Web Minislot card (ref 66244)" "netxml-ups (experimental)" "Eaton" "ups" "5" "various models (SNMP mode)" "SNMP/Web Minislot card (ref 66244)" "snmp-ups (experimental)" +"Eaton" "ups" "5" "various models (SNMP mode)" "Eaton Gigabit Network Card (Network-M2)" "snmp-ups (experimental)" "Eaton" "ups" "5" "various models (serial mode)" "Management Card Contact (ref 66104)" "mge-shut or mge-utalk" "Eaton" "pdu" "5" "ePDU Managed" "" "snmp-ups" "Eaton" "pdu" "5" "ePDU Switched" "" "snmp-ups" diff --git a/docs/man/snmp-ups.txt b/docs/man/snmp-ups.txt index f45462b3e3..28706b01a4 100644 --- a/docs/man/snmp-ups.txt +++ b/docs/man/snmp-ups.txt @@ -35,7 +35,8 @@ as well as any others supporting the APC POWERNET MIB Socomec Sicon UPS with Netvision Web/SNMP management card/external box *pw*:: -Powerware devices with ConnectUPS SNMP cards +Powerware devices with ConnectUPS SNMP cards, as well as UPSes with +Eaton Gigabit Network Cards (Network-M2) *pxgx_ups*:: Eaton devices with Power Xpert Gateway UPS Card From 5763024cc54d0d3823164ff32199491834c1feb7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 13 Oct 2022 12:36:28 +0200 Subject: [PATCH 0021/1232] Update AUTHORS --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 75398df85e..123de62b2f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -177,4 +177,4 @@ D: Author of asem driver N: zakx E: zakx@zakx.de -D: Updating device support docs after unneccessarily writing a redundant driver first +D: Updating device support docs after unnecessarily writing a redundant driver first From 0533a3e83be446fcc10fbabf3d0beccf80be1f81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 13 Oct 2022 12:36:36 +0200 Subject: [PATCH 0022/1232] Update nut.dict --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 8a87b7c79f..1670fe4b85 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3042 utf-8 +personal_ws-1.1 en 3043 utf-8 AAS ABI ACFAIL @@ -3032,6 +3032,7 @@ xxxxAP youruid yyy zaac +zakx zfs zinto zlib From d29685b66fbbb0f2fcb5b1f5c0fec890a94fa2fd Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Thu, 13 Oct 2022 16:58:35 +0200 Subject: [PATCH 0023/1232] Fix index computed issue when OID is absent --- drivers/snmp-ups.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 791fd123fd..6c95443cd8 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -346,7 +346,7 @@ void upsdrv_shutdown(void) /* set shutdown and autostart delay */ set_delays(); - + /* Try to shutdown with delay */ if (su_instcmd("shutdown.return", NULL) == STAT_INSTCMD_HANDLED) { /* Shutdown successful */ @@ -2294,9 +2294,6 @@ static int base_snmp_template_index(const snmp_info_t *su_info_p) char test_OID[SU_INFOSIZE]; snmp_info_flags_t template_type = get_template_type(su_info_p->info_type); - if (!su_info_p->OID) - return base_index; - upsdebugx(3, "%s: OID template = %s", __func__, su_info_p->OID); /* Try to differentiate between template types which may have @@ -2321,6 +2318,10 @@ static int base_snmp_template_index(const snmp_info_t *su_info_p) } base_index = template_index_base; + /* If no OID defined, now we can return the good index computed */ + if (!su_info_p->OID) + return base_index; + if (template_index_base == -1) { /* not initialised yet */ From b3e5fab0b09c6d4629363f0a5a7145da3e39d556 Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Thu, 13 Oct 2022 16:59:53 +0200 Subject: [PATCH 0024/1232] Fix outlets display Add global current --- drivers/apc-epdu-mib.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/apc-epdu-mib.c b/drivers/apc-epdu-mib.c index db8f9ee5a6..22afea94c3 100644 --- a/drivers/apc-epdu-mib.c +++ b/drivers/apc-epdu-mib.c @@ -60,41 +60,48 @@ static snmp_info_t apc_epdu_mib[] = { { "device.version", ST_FLAG_STRING, SU_INFOSIZE, " .1.3.6.1.4.1.318.1.1.30.2.1.1.3.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* Input */ + /* ePDUPhaseTableSize = INTEGER: 1 */ + { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.30.3.0", NULL, SU_FLAG_OK, NULL }, /* ePDUDeviceStatusActivePower.1 = INTEGER: 785 */ { "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, - /* FIXME: Take first phase for global */ + /* Take first phase for global if monophase */ /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ - { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, - /* ePDUPhaseTableSize = INTEGER: 1 */ - { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.30.3.0", NULL, SU_FLAG_OK, NULL }, + { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_1, NULL }, + /* Take first phase for global if monophase */ + /* ePDUPhaseStatusCurrent.1 = INTEGER: 355 */ + { "input.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_1, NULL }, + + /* Only if triphase */ /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ - { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusVoltage.2 = INTEGER: 2304 */ - { "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusVoltage.3 = INTEGER: 2304 */ - { "input.L3-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L3-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusCurrent.1 = INTEGER: 355 */ - { "input.L1.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L1.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusCurrent.2 = INTEGER: 355 */ - { "input.L2.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L2.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusCurrent.3 = INTEGER: 355 */ - { "input.L3.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L3.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusActivePower.1 = INTEGER: 785 */ - { "input.L1.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L1.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusActivePower.2 = INTEGER: 785 */ - { "input.L2.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L2.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.2", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusActivePower.3 = INTEGER: 785 */ - { "input.L3.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, + { "input.L3.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.6.3", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* Outlets */ /* ePDUOutletTableSize.0 = INTEGER: 1 */ { "outlet.count", 0, 1, ".1.3.6.1.4.1.318.1.1.30.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ePDUOutletStatusIndex.%i = INTEGER: 1 */ { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.1.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + /* ePDUOutletStatusModule.%i= INTEGER: 1 */ + { "outlet.%i.name", 0, 1, ".1.3.6.1.4.1.318.1.1.30.6.2.1.2.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, /* ePDUOutletStatusNumber.%i = INTEGER: 1 */ - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.3.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + { "outlet.%i.desc", 0, 1, NULL, "Outlet %i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_OUTLET, NULL }, /* ePDUOutletStatusState.%i = INTEGER: off(1) */ - { "outlet.%i.status", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, &apc_epdu_sw_outlet_status_info[0] }, + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_OUTLET, &apc_epdu_sw_outlet_status_info[0] }, /* Also use this OID to determine switchability ; its presence means "yes" */ /* ePDUOutletStatusState.%i = INTEGER: off(1) */ { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", "yes", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_epdu_sw_outlet_switchability_info[0] }, From e8436628179d74e1f0c44d51e75df343704a045b Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Thu, 13 Oct 2022 17:58:07 +0200 Subject: [PATCH 0025/1232] Fix bad traduction in code --- drivers/apc-epdu-mib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/apc-epdu-mib.c b/drivers/apc-epdu-mib.c index 22afea94c3..e513252b63 100644 --- a/drivers/apc-epdu-mib.c +++ b/drivers/apc-epdu-mib.c @@ -64,14 +64,14 @@ static snmp_info_t apc_epdu_mib[] = { { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.30.3.0", NULL, SU_FLAG_OK, NULL }, /* ePDUDeviceStatusActivePower.1 = INTEGER: 785 */ { "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.30.2.1.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, - /* Take first phase for global if monophase */ + /* Take first phase for global if single phase */ /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_1, NULL }, - /* Take first phase for global if monophase */ + /* Take first phase for global if single phase */ /* ePDUPhaseStatusCurrent.1 = INTEGER: 355 */ { "input.current", 0, 0.01, ".1.3.6.1.4.1.318.1.1.30.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_1, NULL }, - /* Only if triphase */ + /* Only if tree-phase */ /* ePDUPhaseStatusVoltage.1 = INTEGER: 2304 */ { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.30.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID | SU_INPUT_3, NULL }, /* ePDUPhaseStatusVoltage.2 = INTEGER: 2304 */ From 5ec273e81deb2b3bf73aa76c9d1d07508e5117ce Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 14 Oct 2022 21:54:06 +0200 Subject: [PATCH 0026/1232] Update snmp-ups.c Avoid potential NULL pointer dereference in a debug printout --- drivers/snmp-ups.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 6c95443cd8..20a983eb5e 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -2294,7 +2294,8 @@ static int base_snmp_template_index(const snmp_info_t *su_info_p) char test_OID[SU_INFOSIZE]; snmp_info_flags_t template_type = get_template_type(su_info_p->info_type); - upsdebugx(3, "%s: OID template = %s", __func__, su_info_p->OID); + upsdebugx(3, "%s: OID template = %s", __func__, + (su_info_p->OID ? su_info_p->OID : "") ); /* Try to differentiate between template types which may have * different indexes ; and store it to not redo it again */ From 5a813453919b163841d1a0dd8a50be4a07effc0a Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Tue, 18 Oct 2022 17:53:23 +0200 Subject: [PATCH 0027/1232] Fix walk issue with snmpv3 (** add type error execption **) --- drivers/snmp-ups.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 20a983eb5e..68fba9d3be 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -1156,7 +1156,20 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) snmp_free_pdu(response); break; } else { - numerr = 0; + /* Checked the "type" field of the returned varbind if it is a type error + * exception (only applicable with SNMPv2 or SNMPv3 protocol) */ + 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); + break; + } + else { + /* no error */ + numerr = 0; + } } nb_iteration++; From 93237c240ac0e52ba138dc75ddf8e537c5f4ab6b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Oct 2022 11:29:10 +0200 Subject: [PATCH 0028/1232] drivers/snmp-ups.c: apply comments from PR review to make code better understandable [#1682] --- drivers/snmp-ups.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 68fba9d3be..ecb781598c 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -1156,8 +1156,12 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) snmp_free_pdu(response); break; } else { - /* Checked the "type" field of the returned varbind if it is a type error - * exception (only applicable with SNMPv2 or SNMPv3 protocol) */ + /* Checked the "type" field of the returned varbind if + * it is a type error exception (only applicable with + * SNMPv2 or SNMPv3 protocol, would not happen with + * 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) { From 315b6da1583d0021017484bd7c7aa4cac5165abe Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Oct 2022 11:37:54 +0200 Subject: [PATCH 0029/1232] NEWS: fix for snmp-ups type error handling [#1682] --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index a57558c191..c16e1cbce3 100644 --- a/NEWS +++ b/NEWS @@ -99,6 +99,8 @@ https://github.com/networkupstools/nut/milestone/8 * IETF MIB mapping updated for data points where negative readings are invalid [#1558] * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] + * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item + in the middle has a type error [#1682] - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] From 8eb4f2a00ee6d25a9e50d0ed06ef06884baf215a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Oct 2022 11:38:25 +0200 Subject: [PATCH 0030/1232] m4/nut_check_python.m4: clarify message for "Version reported ... not suitable"" --- m4/nut_check_python.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 6773d44413..9a13513d37 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -40,7 +40,7 @@ AC_DEFUN([NUT_CHECK_PYTHON], AS_IF([test -n "${PYTHON}"], [ AS_IF([test x"`$PYTHON -c 'import sys; print (sys.version_info >= (2, 6))'`" = xTrue], [PYTHON_VERSION_REPORT=" (`$PYTHON -c 'import sys; print (sys.version_info)'`)"], - [AC_MSG_WARN([Version reported by ${PYTHON} was not suitable]) + [AC_MSG_WARN([Version reported by ${PYTHON} was not suitable as python]) PYTHON=no]) ]) @@ -104,7 +104,7 @@ AC_DEFUN([NUT_CHECK_PYTHON2], AS_IF([test -n "${PYTHON2}"], [ AS_IF([test x"`$PYTHON2 -c 'import sys; print (sys.version_info >= (2, 6) and sys.version_info < (3, 0))'`" = xTrue], [PYTHON2_VERSION_REPORT=" (`$PYTHON2 -c 'import sys; print (sys.version_info)'`)"], - [AC_MSG_WARN([Version reported by ${PYTHON2} was not suitable]) + [AC_MSG_WARN([Version reported by ${PYTHON2} was not suitable as python2]) PYTHON2=no]) ]) @@ -168,7 +168,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], AS_IF([test -n "${PYTHON3}"], [ AS_IF([test x"`$PYTHON3 -c 'import sys; print (sys.version_info >= (3, 0))'`" = xTrue], [PYTHON3_VERSION_REPORT=" (`$PYTHON3 -c 'import sys; print (sys.version_info)'`)"], - [AC_MSG_WARN([Version reported by ${PYTHON3} was not suitable]) + [AC_MSG_WARN([Version reported by ${PYTHON3} was not suitable as python3]) PYTHON3=no]) ]) From 6000f9eb735d65c24def81ebf33aa16f277e7957 Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Fri, 21 Oct 2022 02:20:35 +0000 Subject: [PATCH 0031/1232] huawei-ups2000.txt: document another UPS2000-A-1KTTS. This commit adds UPS2000-A-1KTTS with another firmware version (V2R1C1SPC50) to the list of tested UPS models. Thanks @ultinous-dancsa for reporting it [1]. [1] https://github.com/networkupstools/nut/issues/1017#issuecomment-1020013055 Signed-off-by: Yifeng Li --- docs/man/huawei-ups2000.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/man/huawei-ups2000.txt b/docs/man/huawei-ups2000.txt index 5cf7c1a29a..14c8377f30 100644 --- a/docs/man/huawei-ups2000.txt +++ b/docs/man/huawei-ups2000.txt @@ -36,6 +36,7 @@ but more testers are needed. Currently, it has been tested on the following models. * UPS2000-A-1KTTS (firmware: UPS2000A, V2R1C1SPC40, P1.0-D1.0) +* UPS2000-A-1KTTS (firmware: UPS2000A, V2R1C1SPC50, P1.0-D1.0) * UPS2000-A-2KTTS (firmware: UPS2000A, V2R1C1SPC50, P1.0-D1.0) * UPS2000-G-1KRTS (firmware: UPS2000A, V2R1C1SPC40, P1.0-D1.0) * UPS2000-G-3KRTS (firmware: UPS2000A, V2R1C1SPC40, P1.0-D1.0) From 0b18b3f7edf3c69e6a3fdfc80cd8fddfb3a44d56 Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Fri, 21 Oct 2022 08:00:09 +0000 Subject: [PATCH 0032/1232] huawei-ups2000.txt: document another UPS2000-G-1KRTS. This is another newer "UPS2000-G" variant encountered by a user in the wild and reported [1] to me. [1] Personal communication, thanks for reporting. Signed-off-by: Yifeng Li --- docs/man/huawei-ups2000.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/man/huawei-ups2000.txt b/docs/man/huawei-ups2000.txt index 14c8377f30..51418d9634 100644 --- a/docs/man/huawei-ups2000.txt +++ b/docs/man/huawei-ups2000.txt @@ -39,6 +39,7 @@ Currently, it has been tested on the following models. * UPS2000-A-1KTTS (firmware: UPS2000A, V2R1C1SPC50, P1.0-D1.0) * UPS2000-A-2KTTS (firmware: UPS2000A, V2R1C1SPC50, P1.0-D1.0) * UPS2000-G-1KRTS (firmware: UPS2000A, V2R1C1SPC40, P1.0-D1.0) +* UPS2000-G-1KRTS (firmware: UPS2000G, V2R1C1SPC50, P1.0-D1.0) * UPS2000-G-3KRTS (firmware: UPS2000A, V2R1C1SPC40, P1.0-D1.0) * UPS2000-G-3KRTS (firmware: UPS2000G, V2R1C1SPC50, P1.0-D1.0) From 45e0a9bf22b6bbb52d469fc10191a176a52273f3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 1 Nov 2022 21:56:52 +0100 Subject: [PATCH 0033/1232] common/common.c: become_user(): log change of UID/GID (or inability to do so) --- common/common.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 177fc45d61..13b21d6a56 100644 --- a/common/common.c +++ b/common/common.c @@ -268,8 +268,12 @@ void become_user(struct passwd *pw) { #ifndef WIN32 /* if we can't switch users, then don't even try */ - if ((geteuid() != 0) && (getuid() != 0)) + if ((geteuid() != 0) && (getuid() != 0)) { + upsdebugx(1, "Can not become_user(%s): not root initially, " + "remaining UID=%jd GID=%jd", + pw->pw_name, (intmax_t)getuid(), (intmax_t)getgid()); return; + } if (getuid() == 0) if (seteuid(0)) @@ -283,8 +287,13 @@ void become_user(struct passwd *pw) if (setuid(pw->pw_uid) == -1) fatal_with_errno(EXIT_FAILURE, "setuid"); + + upsdebugx(1, "Succeeded to become_user(%s): now UID=%jd GID=%jd", + pw->pw_name, (intmax_t)getuid(), (intmax_t)getgid()); #else NUT_UNUSED_VARIABLE(pw); + + upsdebugx(1, "Can not become_user(%s): not implemented on this platform", pw->pw_name); #endif } From 5135f8bff5d0dfa2ef3db198026772a19702549e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 1 Nov 2022 21:59:19 +0100 Subject: [PATCH 0034/1232] common/common.c: chroot_start(): log entering chroot jail (or inability to do so) --- common/common.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/common.c b/common/common.c index 13b21d6a56..e7171d8fb0 100644 --- a/common/common.c +++ b/common/common.c @@ -307,11 +307,16 @@ void chroot_start(const char *path) if (chroot(path)) fatal_with_errno(EXIT_FAILURE, "chroot(%s)", path); +#else + upsdebugx(1, "Can not chroot into %s: not implemented on this platform", path); #endif + if (chdir("/")) fatal_with_errno(EXIT_FAILURE, "chdir(/)"); +#ifndef WIN32 upsdebugx(1, "chrooted into %s", path); +#endif } #ifdef WIN32 From 326f90866dbf557a86928a0ab1aee3808cfd8d62 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 1 Nov 2022 22:06:45 +0100 Subject: [PATCH 0035/1232] tests/NIT/nit.sh: expand permissions for NUT_CONFPATH/*.conf if started as root (tested daemons cannot read them otherwise) --- tests/NIT/nit.sh | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 04688131fb..0883f95369 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -322,7 +322,13 @@ STATEPATH "$NUT_STATEPATH" LISTEN localhost $NUT_PORT EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: upsd.conf" - chmod 640 "$NUT_CONFPATH/upsd.conf" + + if [ "`id -u`" = 0 ]; then + log_info "Test script was started by 'root' - expanding permissions for '$NUT_CONFPATH/upsd.conf' so unprivileged daemons (after de-elevation) may read it" + chmod 644 "$NUT_CONFPATH/upsd.conf" + else + chmod 640 "$NUT_CONFPATH/upsd.conf" + fi # Some systems listining on symbolic "localhost" actually # only bind to IPv6, and Python telnetlib resolves IPv4 @@ -384,7 +390,13 @@ generatecfg_upsdusers_trivial() { upsmon secondary EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: upsd.users" - chmod 640 "$NUT_CONFPATH/upsd.users" + + if [ "`id -u`" = 0 ]; then + log_info "Test script was started by 'root' - expanding permissions for '$NUT_CONFPATH/upsd.users' so unprivileged daemons (after de-elevation) may read it" + chmod 644 "$NUT_CONFPATH/upsd.users" + else + chmod 640 "$NUT_CONFPATH/upsd.users" + fi } ### upsmon.conf: ################################################## @@ -398,7 +410,13 @@ generatecfg_upsmon_trivial() { echo "DEBUG_MIN ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/upsmon.conf" || exit fi ) || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" - chmod 640 "$NUT_CONFPATH/upsmon.conf" + + if [ "`id -u`" = 0 ]; then + log_info "Test script was started by 'root' - expanding permissions for '$NUT_CONFPATH/upsmon.conf' so unprivileged daemons (after de-elevation) may read it" + chmod 644 "$NUT_CONFPATH/upsmon.conf" + else + chmod 640 "$NUT_CONFPATH/upsmon.conf" + fi } generatecfg_upsmon_master() { @@ -437,8 +455,13 @@ generatecfg_ups_trivial() { echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit fi ) || die "Failed to populate temporary FS structure for the NIT: ups.conf" - chmod 640 "$NUT_CONFPATH/ups.conf" + if [ "`id -u`" = 0 ]; then + log_info "Test script was started by 'root' - expanding permissions for '$NUT_CONFPATH/ups.conf' so unprivileged daemons (after de-elevation) may read it" + chmod 644 "$NUT_CONFPATH/ups.conf" + else + chmod 640 "$NUT_CONFPATH/ups.conf" + fi } generatecfg_ups_dummy() { From 2ed0162b5fd413305b3c8db275d4e43559980220 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 2 Nov 2022 10:09:29 +0100 Subject: [PATCH 0036/1232] NEWS: we log uid/gid/chroot changes since 2.8.1 [#1694] --- NEWS | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c16e1cbce3..a5ff51861a 100644 --- a/NEWS +++ b/NEWS @@ -60,8 +60,12 @@ https://github.com/networkupstools/nut/milestone/8 * Fixed building of NUT man pages when just a few drivers are selected by `configure` script for custom builds [#1467] + - We lacked log information about changes of chroot jail (uncommon) and + of uid/gid (everywhere), which makes troubleshooting harder (e.g. lack + of access to config files or USB device nodes). Now we have it [#1694] + - huawei-ups2000 is now known to support more devices, noted in docs and - for auto-detection [#1448] + for auto-detection [#1448, #1684] - nutdrv_qx updates: * the `voltronic_qs_protocol` should now accept both "V" (as before) From b5b434f72f38bd32ad38941760b2833c75753533 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Nov 2022 13:50:22 +0100 Subject: [PATCH 0037/1232] Update NEWS --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a5ff51861a..6fe074f6bc 100644 --- a/NEWS +++ b/NEWS @@ -61,7 +61,7 @@ https://github.com/networkupstools/nut/milestone/8 by `configure` script for custom builds [#1467] - We lacked log information about changes of chroot jail (uncommon) and - of uid/gid (everywhere), which makes troubleshooting harder (e.g. lack + of UID/GID (everywhere), which makes troubleshooting harder (e.g. lack of access to config files or USB device nodes). Now we have it [#1694] - huawei-ups2000 is now known to support more devices, noted in docs and From 78f879aa072885097013b0d25332244478aff3cd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Nov 2022 13:50:24 +0100 Subject: [PATCH 0038/1232] Update nut.dict --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 1670fe4b85..42a587ef59 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3043 utf-8 +personal_ws-1.1 en 3044 utf-8 AAS ABI ACFAIL @@ -383,6 +383,7 @@ Fuß GCCVER GES GETADDRINFO +GID GKrellM GND GPL From 55042401d1849e3caa9d8efeefdf93f6a39a22f4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 6 Nov 2022 07:28:28 +0100 Subject: [PATCH 0039/1232] docs/config-prereqs.txt: update freeipmi -largp install for OpenBSD (6.4 + 6.5 checked) --- docs/config-prereqs.txt | 11 +---------- docs/nut.dict | 5 ++++- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 4082d3994f..53cb168b7c 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -598,20 +598,11 @@ default site. :; pkg_add \ dash ksh93 ------- - -[NOTE] -====== -With OpenBSD 6.4, building against freeipmi failed: its libtool -recipes referenced `-largp` which did not get installed in the system. -Maybe some more packages are needed explicitly? -Was not yet retried with OpenBSD 6.5. ------- :; pkg_add \ + argp-standalone \ freeipmi ------ -====== Recommended: ------ diff --git a/docs/nut.dict b/docs/nut.dict index 42a587ef59..5c7f750746 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3044 utf-8 +personal_ws-1.1 en 3047 utf-8 AAS ABI ACFAIL @@ -466,6 +466,7 @@ Håvard IANA IC ID's +IDE IDEN IDentifiers IFBETWEEN @@ -1431,6 +1432,7 @@ altroot altroots amd anded +antivirus aod aon ap @@ -1447,6 +1449,7 @@ archlinux arduino arg argc +argp args argv armac From 796156434d057a49205b98ddb6b3836dad903d51 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 9 Nov 2022 21:58:40 +0100 Subject: [PATCH 0040/1232] scripts/augeas/gen-nutupsconf-aug.py.in: skip a false-positive from Augeas driver options --- scripts/augeas/gen-nutupsconf-aug.py.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/augeas/gen-nutupsconf-aug.py.in b/scripts/augeas/gen-nutupsconf-aug.py.in index 04b6fa1b2a..6132ccb37b 100755 --- a/scripts/augeas/gen-nutupsconf-aug.py.in +++ b/scripts/augeas/gen-nutupsconf-aug.py.in @@ -84,6 +84,9 @@ if __name__ == '__main__': # 1.4/ Extract variable names for line in matchResults: + if ("Could not addvar" in line): + # Debug trace e.g. in snmp-ups.c + continue row = line.split(',') if len(row) >= 2: # Absence of quotes indicate that we have a #define From 2b9ca931d4e84e10bbf603a87dd942e45d60c00e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 10 Nov 2022 10:34:04 +0100 Subject: [PATCH 0041/1232] docs/nut-names.txt: clarify "unmapped.x.y" not-quite-namespace --- docs/nut-names.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index efe1ae28f4..f5b3758801 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -34,6 +34,17 @@ a better name later, clients that already use the undocumented variable will break when it is eventually changed. An explicitly "experimental" data point is less surprising in this regard. +Similarly, some source files (`drivers/*-mib.c` and `drivers/*-hid.c`) +may mention data point names following the pattern of `unmapped.x.y`. +These are generated by helper scripts which walk the reports from SNMP +and USB HID devices, respectively `scripts/subdriver/gen-snmp-subdriver.sh` +and `scripts/subdriver/gen-usbhid-subdriver.sh`, and assign names based on +strings in those reports. The `unmapped` entries should not be exposed in +"production" builds of the NUT drivers. They are an aid for developers to +know that such entries are served by their device, so an existing standard +NUT name can be assigned for the concept (or new name negotiated with the +community), but are normally hidden with `#if 0` clauses. + NOTE: In the descriptions, "opaque" means programs should not attempt to parse the value for that variable as it may vary greatly from one UPS (or similar device) to the next. These strings are best handled directly From 252e0f5f8b384e5a4badff1fcad9fe727db9f8b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 10 Nov 2022 18:29:43 +0100 Subject: [PATCH 0042/1232] scripts/Windows/README: do not hardcode /usr/$ARCH when we have $PREFIX --- scripts/Windows/README | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/Windows/README b/scripts/Windows/README index 384812a17b..1867e766bf 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -111,10 +111,10 @@ or - also export the following compilation flags: ------ -:; export CFLAGS="$CFLAGS -D_POSIX=1 -I/usr/$ARCH/include/" -:; export CXXFLAGS="$CXXFLAGS -D_POSIX=1 -I/usr/$ARCH/include/" -:; export LDFLAGS="$LDFLAGS -L/usr/$ARCH/lib/" -:; export PKG_CONFIG_PATH="$PREFIX"/lib/pkgconfig +:; export CFLAGS="$CFLAGS -D_POSIX=1 -I${PREFIX}/include/" +:; export CXXFLAGS="$CXXFLAGS -D_POSIX=1 -I${PREFIX}/include/" +:; export LDFLAGS="$LDFLAGS -L${PREFIX}/lib/" +:; export PKG_CONFIG_PATH="${PREFIX}"/lib/pkgconfig ------ - prepare the download and build area, e.g. to match copy-paste instructions @@ -155,9 +155,9 @@ You can also compile it (where that is still needed) using: :; tar xzf "$DLDIR"/pthreads-w32-2-8-0-release.tar.gz :; cd pthreads-w32-2-8-0-release/ :; make -f GNUmakefile "CROSS=$ARCH-" $BUILD_FLAG GC-inlined - :; sudo cp *.dll /usr/$ARCH/pthreads/lib/ - :; sudo cp *.a /usr/$ARCH/lib/ - :; sudo cp pthread.h sched.h semaphore.h /usr/$ARCH/pthreads/include + :; sudo cp *.dll ${PREFIX}/pthreads/lib/ + :; sudo cp *.a ${PREFIX}/lib/ + :; sudo cp pthread.h sched.h semaphore.h ${PREFIX}/pthreads/include MinGW regex library @@ -473,7 +473,7 @@ net-snmp :; yes "" | ./configure --prefix="$PREFIX" $HOST_FLAG \ --with-default-snmp-version=3 --disable-agent --disable-daemon \ --with-sys-contact="" --with-sys-location="" --with-logfile=none \ - --with-persistent-directory=/usr/$ARCH/var/net-snmp \ + --with-persistent-directory="${PREFIX}/var/net-snmp" \ --disable-embedded-perl --without-perl-modules --disable-perl-cc-checks \ --enable-shared # NOTE: ./configure script may ask a few questions, or may just print @@ -488,7 +488,7 @@ NOTE: net-snmp tends to only `make` a static-linking library for Windows by default (the shared library only appears with `LDFLAGS` proposed above). In this case consumers must link not only with `-lnetsnmp` but also its dependencies explicitly -- see `Libs.private` line in `netsnmp.pc` of -your build (or installation in `/usr/$ARCH/lib/pkgconfig/netsnmp.pc`). +your build (or installation in `${PREFIX}/lib/pkgconfig/netsnmp.pc`). Builds can extract this info with `pkg-config --libs --static netsnmp` as NUT scenarios do (for mingw, if shared-linking attempt fails). @@ -540,7 +540,7 @@ Needed for glib2 (further for avahi). :; ./configure --prefix="$PREFIX" $HOST_FLAG :; make all :; sudo make install - :; sudo ln -s libpcre2-posix.pc /usr/$ARCH/lib/pkgconfig/libpcre.pc + :; sudo ln -s libpcre2-posix.pc ${PREFIX}/lib/pkgconfig/libpcre.pc gettext/libintl @@ -706,7 +706,7 @@ targets. NOTE: For other ways of building and packaging, it might make sense for a packaged delivery to also `make install DESTDIR=.../nut_install` from the sources of dependency projects built above, or at least to copy the -built `*.dll` files from `$PREFIX/bin` to `nut_install/bin`. For those +built `*.dll` files from `${PREFIX}/bin` to `nut_install/bin`. For those dependencies that are listed above, the script does this best-effort activity (does not fail if some are missing, but running the programs can fail later). From 916472f6f033b2599be0741a599f040f786cf670 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 10 Nov 2022 18:52:56 +0100 Subject: [PATCH 0043/1232] scripts/Windows/README, docs/config-prereqs.txt: document missing bits for net-snmp in MSYS2 [#1475] --- docs/config-prereqs.txt | 6 ++++-- scripts/Windows/README | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 53cb168b7c..8a4fc62027 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -1173,9 +1173,11 @@ involved is very important. * https://github.com/ccache/ccache/discussions/784 * https://sourceforge.net/p/msys2/tickets/253/ -Notable packages not found in the repo: +Notable packages *not found* in the repo: -* snmp (net-snmp, ucd-snmp) +* snmp (net-snmp, ucd-snmp) -- instructions in `scripts/Windows/README` + document now covers building it from source in MSYS2 MinGW x64 environment, + essentially same as for Linux cross builds with proper `ARCH` and `PREFIX` * libregex (C version, direct NUT `configure` script support was added by the Windows branch); MSYS2 however includes `libpcre` pulled by some of the dependencies above... diff --git a/scripts/Windows/README b/scripts/Windows/README index 1867e766bf..bd23a4077d 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -12,7 +12,9 @@ test and fix programs, re-enable some code just commented away by ifdefs...) NOTE: It is possible to prepare a Windows machine with tools and prerequisites for building NUT natively, as detailed in `docs/config-prereqs.txt` and easily -handled by NUT common `ci_build.sh` script. Possibly, the instructions below +handled by NUT common `ci_build.sh` script. Most prerequisites are already +packaged in that environment, but notably net-snmp is missing -- but can be +built from source following this document. Possibly, the instructions below would converge there over time to keep it simple. For additional reference about prerequisite preparation and further ideas for @@ -102,6 +104,22 @@ or :; PREFIX="/usr/$ARCH" ------ +- NOTE: Technically, these instructions may apply to builds with MinGW on + Windows semi-natively (e.g. to add the net-snmp libraries which are not + packaged currently). Generally you can use environment variables set by + different launchers of MinGW terminal sessions depending on the target + profile (32/64 bit, gcc/clang, libc implementation...): +------ +:; export ARCH="$MINGW_CHOST" +:; PREFIX="$MINGW_PREFIX/$ARCH" +------ + You might want to verify that it sets values similar to: +------ +:; set | grep -E '^(ARCH|PREFIX)=' +#export ARCH="x86_64-w64-mingw32" +#PREFIX="/mingw64/$ARCH" +------ + - on Debian/Ubuntu style systems also: ------ :; BUILD_FLAG="--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE`" @@ -482,6 +500,7 @@ net-snmp # The following long `LDFLAGS` ensure that shared `libnetsnmp-40.dll` # gets built and later installed (and siblings which NUT does not use): :; make LDFLAGS="-no-undefined -lws2_32 -lregex -Xlinker --ignore-unresolved-symbol=_app_name_long -Xlinker --ignore-unresolved-symbol=app_name_long" + :; find . -type f -name '*.dll' -o -name '*.dll.a' :; sudo make install NOTE: net-snmp tends to only `make` a static-linking library for Windows From 78cdbc4cab3d8c88b0270d47bb9f7c1bfeaedb3b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 09:29:10 +0100 Subject: [PATCH 0044/1232] scripts/Windows/README: update envvar setting suggestions for Windows MSYS2 builds [#1475] --- scripts/Windows/README | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/scripts/Windows/README b/scripts/Windows/README index bd23a4077d..eecf4b88a4 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -106,18 +106,36 @@ or - NOTE: Technically, these instructions may apply to builds with MinGW on Windows semi-natively (e.g. to add the net-snmp libraries which are not - packaged currently). Generally you can use environment variables set by - different launchers of MinGW terminal sessions depending on the target - profile (32/64 bit, gcc/clang, libc implementation...): + packaged for MSYS2 MinGW currently). Generally you can use environment + variables set by different launchers of MinGW terminal sessions depending + on the target profile (32/64 bit, gcc/clang, libc implementation...) + +** For a "native build" directly for consumption in the currently configured + environment, you would not use cross-build path in `PREFIX` and not set + the `HOST_FLAG` value: ++ +------ +:; export ARCH="$MINGW_CHOST" +:; PREFIX="$MINGW_PREFIX" +:; export HOST_FLAG="" +------ + +** If you wanted a "real cross-build" for a different MinGW environment, you + might want to set those (but the NUT build would then need to be told to + search for headers, libraries and pkg-config data in extra locations): ++ ------ :; export ARCH="$MINGW_CHOST" :; PREFIX="$MINGW_PREFIX/$ARCH" +:; export HOST_FLAG="--host=$ARCH" ------ - You might want to verify that it sets values similar to: +** You might want then to verify that it sets values you expect with a command + like this: ++ ------ -:; set | grep -E '^(ARCH|PREFIX)=' +:; set | grep -E '^(ARCH|PREFIX|HOST_FLAG)=' #export ARCH="x86_64-w64-mingw32" -#PREFIX="/mingw64/$ARCH" +#PREFIX="/mingw64/x86_64-w64-mingw32" ------ - on Debian/Ubuntu style systems also: From d0c3307b51a40fd9045539cdfc1523dac15400a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 13:39:29 +0100 Subject: [PATCH 0045/1232] scripts/Windows/README: update 'sudo' suggestions for Windows MSYS2 builds [#1475] --- scripts/Windows/README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/Windows/README b/scripts/Windows/README index eecf4b88a4..baa64374d5 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -110,6 +110,9 @@ or variables set by different launchers of MinGW terminal sessions depending on the target profile (32/64 bit, gcc/clang, libc implementation...) +** For `sudo make install` in instructions below, you may have to omit the + `sudo` part if missing in your MSYS2 MinGW environment; + ** For a "native build" directly for consumption in the currently configured environment, you would not use cross-build path in `PREFIX` and not set the `HOST_FLAG` value: From 65908ef6a82dd12e1bf0d118a8c2bd7010905c0a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 13:40:42 +0100 Subject: [PATCH 0046/1232] scripts/Windows/README: update DLDIR and WSDIR definitions --- scripts/Windows/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Windows/README b/scripts/Windows/README index baa64374d5..3d87a2bd5e 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -157,11 +157,11 @@ or ------ - prepare the download and build area, e.g. to match copy-paste instructions - below, it would be like: +below, it would be like: ------ -:; mkdir -p ~/nut-win-deps/"$ARCH" :; DLDIR=~/nut-win-deps -:; WSDIR=~/nut-win-deps/"$ARCH" +:; WSDIR="$DLDIR"/"$ARCH" +:; mkdir -p "$WSDIR" "$DLDIR" ------ ================================================================================ From be0d55f1e0054b8a2a740a806a496874482bf7ab Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 13:45:43 +0100 Subject: [PATCH 0047/1232] appveyor.yml: try to ensure presence of net-snmp in MSYS2 MinGW builds [#1475] --- appveyor.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 00a4f6a308..6e508a8eb3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,6 +51,19 @@ install: C:\msys64\usr\bin\bash -lc 'PATH="/mingw64/bin:$PATH" ; export PATH ; pwd ; ccache -sv || echo "SKIP: Could not query ccache stats"' +before_build: + - cmd: | + REM Ensure we have a net-snmp to build against + REM Adapted from scripts/Windows/README document. + REM Here we hope to build it once, then use the + REM stashed version across Appveyor rebuilds. + REM Preserve the current working directory: + set CHERE_INVOKING=yes + REM Start a 64 bit Mingw environment: + set MSYSTEM=MINGW64 + C:\msys64\usr\bin\bash -lc 'set +e ; date -u; export PATH="/mingw64/bin:$PATH"; export ARCH="$MINGW_CHOST" ; export PREFIX="$MINGW_PREFIX"; export PKG_CONFIG_PATH="${PREFIX}"/lib/pkgconfig ; pkg-config --exists netsnmp && exit ; export CFLAGS="$CFLAGS -D_POSIX=1 -I${PREFIX}/include/" ; export CXXFLAGS="$CXXFLAGS -D_POSIX=1 -I${PREFIX}/include/" ; export LDFLAGS="$LDFLAGS -L${PREFIX}/lib/" ; DLDIR=~/nut-win-deps ; WSDIR="$DLDIR"/"$ARCH" ; mkdir -p "$WSDIR" "$DLDIR" ; if [ -d "$WSDIR/net-snmp-5.9.1/.inst" ]; then cd "$WSDIR/net-snmp-5.9.1/.inst" && rsync -avPHK ./ / && exit ; fi ; if [ -d "$WSDIR/net-snmp-5.9.1" ]; then cd "$WSDIR/net-snmp-5.9.1" && make install -j 8 && exit ; fi ; set -e ; ( cd "$DLDIR" && wget -c https://sourceforge.net/projects/net-snmp/files/net-snmp/5.9.1/net-snmp-5.9.1.tar.gz ) ; cd "$WSDIR" ; rm -rf net-snmp-5.9.1 || true ; tar xzf "$DLDIR"/net-snmp-5.9.1.tar.gz ; cd net-snmp-5.9.1 ; yes "" | ./configure --prefix="$PREFIX" --with-default-snmp-version=3 --disable-agent --disable-daemon --with-sys-contact="" --with-sys-location="" --with-logfile=none --with-persistent-directory="${PREFIX}/var/net-snmp" --disable-embedded-perl --without-perl-modules --disable-perl-cc-checks --enable-shared || exit ; make LDFLAGS="-no-undefined -lws2_32 -lregex -Xlinker --ignore-unresolved-symbol=_app_name_long -Xlinker --ignore-unresolved-symbol=app_name_long" -j 8 || exit ; make -d "`pwd`/.inst" install -j 8 || exit ; make install ; find . -type f -name "*.dll" -o -name "*.dll.a";' + + build_script: - cmd: | REM Preserve the current working directory: @@ -110,6 +123,7 @@ cache: - C:\msys64\home\appveyor\.ccache - C:\msys64\home\appveyor\ccache # likely missing, no problem - but the name is reported in ccache status - C:\msys64\var\cache\pacman\pkg + - C:\msys64\home\appveyor\nut-win-deps # Below we tried to stash binaries of MSYS2 environment # so VM deployment is faster on subsequent builds From 9cf5eb610965eee08b1eb7e22e156e065d1436d1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 13:48:26 +0100 Subject: [PATCH 0048/1232] appveyor.yml: fix comment for config.log artifact --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6e508a8eb3..56e83c07c4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -115,7 +115,7 @@ artifacts: name: Bundle of binary files and FOSS dependencies of NUT for Windows - path: config.log - name: config.log + name: config.log of recent build of NUT for Windows # Example optional cache (depends on file change): # - C:\msys64 -> appveyor.yml From d903389e58b84875f89f2682d9c583dce75db816 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 13:53:49 +0100 Subject: [PATCH 0049/1232] appveyor.yml: fix typo --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 56e83c07c4..a153414d0c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,7 +43,7 @@ install: C:\msys64\usr\bin\bash -lc "date -u; pacman --noconfirm -S --needed base-devel mingw-w64-x86_64-toolchain autoconf-wrapper automake-wrapper libtool mingw-w64-x86_64-libltdl gcc ccache mingw-w64-x86_64-ccache git aspell aspell-en python mingw-w64-x86_64-python-pygments mingw-w64-x86_64-winpthreads-git mingw-w64-x86_64-libusb mingw-w64-x86_64-libusb-compat-git mingw-w64-x86_64-neon libneon-devel mingw-w64-x86_64-libmodbus-git mingw-w64-x86_64-libgd mingw-w64-x86_64-cppunit" - cmd: | REM Assorted stats after package processing: - C:\msys64\usr\bin\bash -lc "date -u; ls la / ; du -ksx / ; date -u; du -ks /var/cache/pacman/pkg; date -u" + C:\msys64\usr\bin\bash -lc "date -u; ls -la / ; du -ksx / ; date -u; du -ks /var/cache/pacman/pkg; date -u" REM Preserve the current working directory: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: From 7684160e4fbddb7d8d12216af45e6b4ef2bb0b88 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 15:02:14 +0100 Subject: [PATCH 0050/1232] Add scripts/Windows/build-mingw-prereqs.sh [#1475] --- scripts/Windows/build-mingw-prereqs.sh | 126 +++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100755 scripts/Windows/build-mingw-prereqs.sh diff --git a/scripts/Windows/build-mingw-prereqs.sh b/scripts/Windows/build-mingw-prereqs.sh new file mode 100755 index 0000000000..df2d8c7311 --- /dev/null +++ b/scripts/Windows/build-mingw-prereqs.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +# Copyright (C) 2022 by Jim Klimov +# Licensed same as NUT +# +# Helper automating the nuances from NUT::scripts/Windows/README +# to provide prerequisites needed in semi-native or cross-builds. +# +# NOTE: Currently constrained to providing net-snmp under MSYS2. +# We can not rely on certain common shell facilities like `true` +# and `false` programs being available (in PATH or at all). +# TODO: Support `make uninstall` attempts for older versions?.. + +prepareEnv() { + [ -n "${MAKE-}" ] || MAKE="make -j 8" + export MAKE + + [ -n "${DLDIR-}" ] || DLDIR=~/nut-win-deps + + if [ -n "${ARCH-}" ] && [ -n "${PREFIX-}" ] ; then + [ -n "${WSDIR-}" ] || WSDIR="$DLDIR"/"$ARCH" + mkdir -p "$WSDIR" "$DLDIR" + return 0 + fi + + BUILD_FLAG="" + HOST_FLAG="" + export HOST_FLAG + if [ -n "${MSYS2_PATH-}" ]; then + # Assume semi-native build for same env + ARCH="$MINGW_CHOST" + PREFIX="$MINGW_PREFIX" + PATH="$PREFIX/bin:$PATH" + export ARCH PATH PREFIX + + if ! (command -v sudo) ; then sudo() ( "$@" ) ; fi + else + # TODO: Select by args, envvars, directory presence... + ARCH="x86_64-w64-mingw32" + #ARCH="i686-w64-mingw32" + + # Assumes Ubuntu/Debian with mingw prepared, per README + HOST_FLAG="--host=$ARCH" + PREFIX="/usr/$ARCH" + + export ARCH PREFIX + + if (command -v dpkg-architecture) ; then + BUILD_FLAG="--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE`" + fi + fi + + CFLAGS="$CFLAGS -D_POSIX=1 -I${PREFIX}/include/" + CXXFLAGS="$CXXFLAGS -D_POSIX=1 -I${PREFIX}/include/" + LDFLAGS="$LDFLAGS -L${PREFIX}/lib/" + PKG_CONFIG_PATH="${PREFIX}"/lib/pkgconfig + + export CFLAGS CXXFLAGS LDFLAGS PKG_CONFIG_PATH + + [ -n "${WSDIR-}" ] || WSDIR="$DLDIR"/"$ARCH" + mkdir -p "$WSDIR" "$DLDIR" +} + +# Provide prerequisites; reentrant (quick skip if installed; quick install if built) +provide_netsnmp() ( + PKGCFG_NAME="netsnmp" + DEP_PRJNAME="net-snmp" + DEP_VERSION="5.9.1" + DEP_DIRNAME="${DEP_PRJNAME}-${DEP_VERSION}" + DEP_ARCHIVE="${DEP_DIRNAME}.tar.gz" + + FORCE=false + if [ x"${1-}" = x"-f" ] ; then FORCE=true ; fi + + set +e + if [ x"$FORCE" = x"false" ] ; then + # TODO: Check version + if pkg-config --exists "$PKGCFG_NAME" ; then return 0 ; fi + + # Quickly install if prebuilt + if [ -d "${WSDIR}/${DEP_DIRNAME}/.inst" ]; then ( + cd "${WSDIR}/${DEP_DIRNAME}/.inst" || exit + (command -v rsync) && rsync -avPHK ./ / && exit + cp -pr ./ / && exit + exit 1 + ) && return 0 + fi + + # no stashed .inst; any Makefile at least? + if [ -s "${WSDIR}/${DEP_DIRNAME}/Makefile" ]; then ( cd "${WSDIR}/${DEP_DIRNAME}" && $MAKE install ) && return ; fi + fi + + # (Re-)make and install from scratch + set -e + ( cd "$DLDIR" && wget -c "https://sourceforge.net/projects/${DEP_PRJNAME}/files/${DEP_PRJNAME}/${DEP_VERSION}/${DEP_ARCHIVE}" ) + + cd "${WSDIR}" + rm -rf ${DEP_DIRNAME} || echo "" + + tar xzf "$DLDIR/${DEP_ARCHIVE}" || exit + cd "./${DEP_DIRNAME}" + + yes "" | ./configure --prefix="$PREFIX" --with-default-snmp-version=3 \ + --disable-agent --disable-daemon --with-sys-contact="" --with-sys-location="" \ + --with-logfile=none --with-persistent-directory="${PREFIX}/var/net-snmp" \ + --disable-embedded-perl --without-perl-modules --disable-perl-cc-checks \ + --enable-shared || exit + + $MAKE LDFLAGS="-no-undefined -lws2_32 -lregex -Xlinker --ignore-unresolved-symbol=_app_name_long -Xlinker --ignore-unresolved-symbol=app_name_long" || exit + + # Beside leaving a pre-install location for future runs, + # this may build some more artifacts: + rm -rf "`pwd`/.inst" || echo "" + $MAKE DESTDIR="`pwd`/.inst" install || exit + + # Summarize what we have got + find ./ -type f -name "*.dll" -o -name "*.dll.a"; + + sudo $MAKE install +) + +prepareEnv || exit + +# TODO: Loop, params, help, etc... +# For now, let it pass "-f" to the builder +provide_netsnmp "$@" From 5b2bad57c3470bdaae15a84cc13f66d5015dc80a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 15:06:37 +0100 Subject: [PATCH 0051/1232] appveyor.yml: use scripts/Windows/build-mingw-prereqs.sh [#1475] --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a153414d0c..06f3b955f7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,7 @@ before_build: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc 'set +e ; date -u; export PATH="/mingw64/bin:$PATH"; export ARCH="$MINGW_CHOST" ; export PREFIX="$MINGW_PREFIX"; export PKG_CONFIG_PATH="${PREFIX}"/lib/pkgconfig ; pkg-config --exists netsnmp && exit ; export CFLAGS="$CFLAGS -D_POSIX=1 -I${PREFIX}/include/" ; export CXXFLAGS="$CXXFLAGS -D_POSIX=1 -I${PREFIX}/include/" ; export LDFLAGS="$LDFLAGS -L${PREFIX}/lib/" ; DLDIR=~/nut-win-deps ; WSDIR="$DLDIR"/"$ARCH" ; mkdir -p "$WSDIR" "$DLDIR" ; if [ -d "$WSDIR/net-snmp-5.9.1/.inst" ]; then cd "$WSDIR/net-snmp-5.9.1/.inst" && rsync -avPHK ./ / && exit ; fi ; if [ -d "$WSDIR/net-snmp-5.9.1" ]; then cd "$WSDIR/net-snmp-5.9.1" && make install -j 8 && exit ; fi ; set -e ; ( cd "$DLDIR" && wget -c https://sourceforge.net/projects/net-snmp/files/net-snmp/5.9.1/net-snmp-5.9.1.tar.gz ) ; cd "$WSDIR" ; rm -rf net-snmp-5.9.1 || true ; tar xzf "$DLDIR"/net-snmp-5.9.1.tar.gz ; cd net-snmp-5.9.1 ; yes "" | ./configure --prefix="$PREFIX" --with-default-snmp-version=3 --disable-agent --disable-daemon --with-sys-contact="" --with-sys-location="" --with-logfile=none --with-persistent-directory="${PREFIX}/var/net-snmp" --disable-embedded-perl --without-perl-modules --disable-perl-cc-checks --enable-shared || exit ; make LDFLAGS="-no-undefined -lws2_32 -lregex -Xlinker --ignore-unresolved-symbol=_app_name_long -Xlinker --ignore-unresolved-symbol=app_name_long" -j 8 || exit ; make -d "`pwd`/.inst" install -j 8 || exit ; make install ; find . -type f -name "*.dll" -o -name "*.dll.a";' + C:\msys64\usr\bin\bash -lc "date -u; export MSYS2_PATH ; bash -x ./scripts/Windows/build-mingw-prereqs.sh" build_script: From 39f12914b6e23f141a115a08685d1e6fe3d3e1a3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 16:06:26 +0100 Subject: [PATCH 0052/1232] scripts/Windows/build-mingw-prereqs.sh: handle possibly missing SUDO differently [#1475] --- scripts/Windows/build-mingw-prereqs.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/Windows/build-mingw-prereqs.sh b/scripts/Windows/build-mingw-prereqs.sh index df2d8c7311..c19c1f19dd 100755 --- a/scripts/Windows/build-mingw-prereqs.sh +++ b/scripts/Windows/build-mingw-prereqs.sh @@ -15,6 +15,12 @@ prepareEnv() { [ -n "${MAKE-}" ] || MAKE="make -j 8" export MAKE + if [ -z "${SUDO-}" ] ; then + SUDO=" " # avoid reeval + if (command -v sudo) ; then SUDO="sudo" ; fi + fi + export SUDO + [ -n "${DLDIR-}" ] || DLDIR=~/nut-win-deps if [ -n "${ARCH-}" ] && [ -n "${PREFIX-}" ] ; then @@ -80,14 +86,14 @@ provide_netsnmp() ( # Quickly install if prebuilt if [ -d "${WSDIR}/${DEP_DIRNAME}/.inst" ]; then ( cd "${WSDIR}/${DEP_DIRNAME}/.inst" || exit - (command -v rsync) && rsync -avPHK ./ / && exit - cp -pr ./ / && exit + (command -v rsync) && $SUDO rsync -avPHK ./ / && exit + $SUDO cp -pr ./ / && exit exit 1 ) && return 0 fi # no stashed .inst; any Makefile at least? - if [ -s "${WSDIR}/${DEP_DIRNAME}/Makefile" ]; then ( cd "${WSDIR}/${DEP_DIRNAME}" && $MAKE install ) && return ; fi + if [ -s "${WSDIR}/${DEP_DIRNAME}/Makefile" ]; then ( cd "${WSDIR}/${DEP_DIRNAME}" && $SUDO $MAKE install ) && return ; fi fi # (Re-)make and install from scratch @@ -116,7 +122,7 @@ provide_netsnmp() ( # Summarize what we have got find ./ -type f -name "*.dll" -o -name "*.dll.a"; - sudo $MAKE install + $SUDO $MAKE install ) prepareEnv || exit From 14ab376f86aa3c579efd2360f1d632b0fc9e78ad Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 16:40:29 +0100 Subject: [PATCH 0053/1232] appveyor.yml: temporarily force rebuild of netsnmp --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 06f3b955f7..782491adf5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,7 @@ before_build: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc "date -u; export MSYS2_PATH ; bash -x ./scripts/Windows/build-mingw-prereqs.sh" + C:\msys64\usr\bin\bash -lc "date -u; export MSYS2_PATH ; bash -x ./scripts/Windows/build-mingw-prereqs.sh -f" build_script: From 0aaa79c19f6df47669dfeeb894772b3458e6cf10 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 11 Nov 2022 20:35:18 +0100 Subject: [PATCH 0054/1232] scripts/Windows/build-mingw-prereqs.sh: use curl if wget fails from sourceforge [#1475] --- scripts/Windows/build-mingw-prereqs.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/Windows/build-mingw-prereqs.sh b/scripts/Windows/build-mingw-prereqs.sh index c19c1f19dd..6f6fa4cb77 100755 --- a/scripts/Windows/build-mingw-prereqs.sh +++ b/scripts/Windows/build-mingw-prereqs.sh @@ -98,7 +98,12 @@ provide_netsnmp() ( # (Re-)make and install from scratch set -e - ( cd "$DLDIR" && wget -c "https://sourceforge.net/projects/${DEP_PRJNAME}/files/${DEP_PRJNAME}/${DEP_VERSION}/${DEP_ARCHIVE}" ) + + # Funny ways to fetch from Sourceforge help get the archive, + # not the download page... For some reason, this bites CI + # builds on Appveyor but not local runs: + ( cd "$DLDIR" && curl -vL "https://sourceforge.net/projects/${DEP_PRJNAME}/files/${DEP_PRJNAME}/${DEP_VERSION}/${DEP_ARCHIVE}" > "${DEP_ARCHIVE}" ) || \ + ( cd "$DLDIR" && wget -c "https://sourceforge.net/projects/${DEP_PRJNAME}/files/${DEP_PRJNAME}/${DEP_VERSION}/${DEP_ARCHIVE}" -O "${DEP_ARCHIVE}" ) cd "${WSDIR}" rm -rf ${DEP_DIRNAME} || echo "" From e37f1c6ec464844c8ee1943d98816bf1ce773fe3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 12 Nov 2022 01:10:07 +0100 Subject: [PATCH 0055/1232] appveyor.yml: disable required forced rebuilds of netsnmp (and debug of build-mingw-prereqs.sh) [#1475] --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 782491adf5..45a5b6e4bf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,7 @@ before_build: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc "date -u; export MSYS2_PATH ; bash -x ./scripts/Windows/build-mingw-prereqs.sh -f" + C:\msys64\usr\bin\bash -lc "date -u; export MSYS2_PATH ; bash ./scripts/Windows/build-mingw-prereqs.sh" build_script: From 1799599aaad6b5a3155261cc77c2024c928a3725 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 11:11:56 +0100 Subject: [PATCH 0056/1232] docs/nut.dict: update for nut-website::projects.txt --- docs/nut.dict | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 5c7f750746..d78164b7c6 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3047 utf-8 +personal_ws-1.1 en 3050 utf-8 AAS ABI ACFAIL @@ -760,6 +760,7 @@ Niels Niklas Niro Nobreaks +NodeJS Nom NomDCV NomVIn @@ -1230,6 +1231,7 @@ Theodor Thierry Tigra Tnn +ToddGreenfield Tomek TopGuard Toth @@ -2960,6 +2962,7 @@ varname varvalue vbatt vc +vectronic vendorid ver verifySourceSig From 130441b06efdb97870b4b99041724bef0e595b4c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 12:00:21 +0100 Subject: [PATCH 0057/1232] docs/nut.dict: update dict --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index d78164b7c6..d221aa4a23 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3050 utf-8 +personal_ws-1.1 en 3052 utf-8 AAS ABI ACFAIL @@ -1814,6 +1814,7 @@ energizerups energysave english enum +env envvar envvars ep @@ -2511,6 +2512,7 @@ pwro px pxgx py +pycparser pydoc pygments pynut From c2502e4d5fafbbd1c0f39e43327e48079d412729 Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Wed, 9 Nov 2022 09:51:17 +0100 Subject: [PATCH 0058/1232] Integrate nLogic pdu (snmp) --- drivers/Makefile.am | 4 +- drivers/eaton-pdu-nlogic-mib.c | 3393 ++++++++++++++++++++++++++++++++ drivers/eaton-pdu-nlogic-mib.h | 30 + drivers/snmp-ups.c | 4 +- 4 files changed, 3428 insertions(+), 3 deletions(-) create mode 100644 drivers/eaton-pdu-nlogic-mib.c create mode 100644 drivers/eaton-pdu-nlogic-mib.h diff --git a/drivers/Makefile.am b/drivers/Makefile.am index f689bd075a..cb75d4b297 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -236,7 +236,7 @@ snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ compaq-mib.c cyberpower-mib.c \ delta_ups-mib.c \ eaton-pdu-genesis2-mib.c eaton-pdu-marlin-mib.c eaton-pdu-marlin-helpers.c \ - eaton-pdu-pulizzi-mib.c eaton-pdu-revelation-mib.c \ + eaton-pdu-pulizzi-mib.c eaton-pdu-revelation-mib.c eaton-pdu-nlogic-mib.c \ eaton-ats16-nmc-mib.c eaton-ats16-nm2-mib.c apc-ats-mib.c eaton-ats30-mib.c \ emerson-avocent-pdu-mib.c \ hpe-pdu-mib.c huawei-mib.c \ @@ -341,7 +341,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi 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 \ apc-pdu-mib.h apc-epdu-mib.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 legrand-hid.h \ - hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h + hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h eaton-pdu-nlogic-mib.h # Define a dummy library so that Automake builds rules for the # corresponding object files. This library is not actually built, diff --git a/drivers/eaton-pdu-nlogic-mib.c b/drivers/eaton-pdu-nlogic-mib.c new file mode 100644 index 0000000000..125ca82029 --- /dev/null +++ b/drivers/eaton-pdu-nlogic-mib.c @@ -0,0 +1,3393 @@ +/* eaton-pdu-nlogic-mib.c - subdriver to monitor eaton-pdu-nlogic SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2022 Eaton (author: Arnaud Quette ) + * + * Note: this subdriver was initially generated as a "stub" by the + * gen-snmp-subdriver script. It must be customized! + * + * 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 "eaton-pdu-nlogic-mib.h" + +#define EATON_PDU_NLOGIC_MIB_VERSION "0.1" + +#define EATON_PDU_NLOGIC_SYSOID ".1.3.6.1.4.1.534.7.1" + +static info_lkp_t eaton_nlogic_unit_switchability_info[] = { + { 1, "yes", NULL, NULL }, + { 2, "no", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t eaton_nlogic_outlet_status_info[] = { + { 1, "off", NULL, NULL }, + { 2, "on", NULL, NULL }, + { 3, "pendingOff", NULL, NULL }, /* transitional status */ + { 4, "pendingOn", NULL, NULL }, /* transitional status */ + { 0, NULL, NULL, NULL } +}; + +/* Note: same as marlin_outlet_type_info + i5-20R */ +static info_lkp_t eaton_nlogic_outlet_type_info[] = { + { 0, "unknown", NULL, NULL }, + { 1, "iecC13", NULL, NULL }, + { 2, "iecC19", NULL, NULL }, + { 3, "i5-20R", NULL, NULL }, + { 10, "uk", NULL, NULL }, + { 11, "french", NULL, NULL }, + { 12, "schuko", NULL, NULL }, + { 20, "nema515", NULL, NULL }, + { 21, "nema51520", NULL, NULL }, + { 22, "nema520", NULL, NULL }, + { 23, "nemaL520", NULL, NULL }, + { 24, "nemaL530", NULL, NULL }, + { 25, "nema615", NULL, NULL }, + { 26, "nema620", NULL, NULL }, + { 27, "nemaL620", NULL, NULL }, + { 28, "nemaL630", NULL, NULL }, + { 29, "nemaL715", NULL, NULL }, + { 30, "rf203p277", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + + +/* EATON_PDU_NLOGIC Snmp2NUT lookup table */ +static snmp_info_t eaton_pdu_nlogic_mib[] = { + +/* Data format: + * { info_type, info_flags, info_len, OID, dfl, flags, oid2info }, + * + * info_type: NUT INFO_ or CMD_ element name + * info_flags: flags to set in addinfo + * info_len: length of strings if ST_FLAG_STRING, multiplier otherwise + * OID: SNMP OID or NULL + * dfl: default value + * flags: snmp-ups internal flags (FIXME: ...) + * oid2info: lookup table between OID and NUT values + */ + + +/* standard MIB items; if the vendor MIB contains better OIDs for + * this (e.g. with daisy-chain support), consider adding those here + */ + { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, + ".1.3.6.1.2.1.1.1.0", + NULL, SU_FLAG_OK, NULL }, + { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, + ".1.3.6.1.2.1.1.4.0", + NULL, SU_FLAG_OK, NULL }, + { "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 collection */ + /* pduManufacturer.1 = STRING: "EATON" */ + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.4.1", + "EATON", SU_FLAG_STATIC, NULL }, + /* pduModel.1 = STRING: "200-240V, 24A, 5.0kVA, 50/60Hz" */ + /* Prefer ".1.3.6.1.2.1.1.1.0" / device.description */ + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.2.1.1.1.0", /*".1.3.6.1.4.1.534.7.1.1.2.1.3.1", */ + "Eaton ePDU", SU_FLAG_STATIC, NULL }, + /* pduSerialNumber.1 = STRING: "WMEL0046" */ + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.8.1", + NULL, SU_FLAG_STATIC, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, + NULL, + "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* pduPartNumber.1 = STRING: "EMSV0001" */ + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.7.1", + SU_FLAG_STATIC, SU_FLAG_OK, NULL }, + /* For daisychain, there is only 1 physical interface! */ + /* pduMACAddress.1 = Hex-STRING: 43 38 2D 34 35 2D 34 34 2D 33 30 2D 39 34 2D 31 */ + { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.14.1", + "", SU_FLAG_STATIC, NULL }, + + /* Number of daisychained units is processed according to present units + * in the chain with new G3 firmware (02.00.0051, since autumn 2017): + * Take string "unitsPresent" (ex: "0,3,4,5"), and count the amount + * of "," separators+1 using an inline function */ + /* FIXME: inline func */ + /* pduNumberPDU.0 = INTEGER: 1 */ + { "device.count", 0, 1, + ".1.3.6.1.4.1.534.7.1.1.1.0", + "0", SU_FLAG_STATIC, + NULL /* &marlin_device_count_info[0] */ /* devices_count */ }, + + /* FIXME: this entry should be SU_FLAG_SEMI_STATIC */ + /* pduFirmwareVersion.1 = STRING: "1.0.6" */ + { "device.firmware", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.5.1", + "", SU_FLAG_OK, NULL }, + /* pduFirmwareVersionTimeStamp.1 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + /* { "unmapped.pduFirmwareVersionTimeStamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.1.2.1.6.1", NULL, SU_FLAG_OK, NULL }, */ + /* pduIdentIndex.1 = INTEGER: 1 */ + /* { "unmapped.pduIdentIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, */ + /* pduName.1 = "" */ + /* FIXME: RFC device.name? */ + { "device.name", ST_FLAG_STRING | ST_FLAG_RW, 63, + ".1.3.6.1.4.1.534.7.1.1.2.1.2.1", + NULL, SU_FLAG_OK, NULL }, + /* pduStatus.1 = INTEGER: 4 */ + /* { "unmapped.pduStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.1.2.1.9.1", NULL, SU_FLAG_OK, NULL }, */ + + /* Input collection */ + /* pduInputPhaseCount.1 = INTEGER: 1 */ + { "input.phases", 0, 1, + ".1.3.6.1.4.1.534.7.1.1.2.1.11.1", + NULL, SU_FLAG_OK, NULL }, + /* pduInputType.1 = INTEGER: 1 */ + /* { "unmapped.pduInputType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, */ + /* pduInputFrequency.1 = INTEGER: 499 */ + { "input.frequency", 0, 0.1, + ".1.3.6.1.4.1.534.7.1.2.1.1.2.1", + NULL, 0, NULL }, + /* pduInputTotalCurrent.1 = INTEGER: 0 */ + { "input.current", 0, 0.01, ".1.3.6.1.4.1.534.7.1.2.1.1.11.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltage.1.1 = INTEGER: 2418 */ + { "input.voltage", 0, 0.1, + ".1.3.6.1.4.1.534.7.1.2.2.1.3.1.1", + NULL, SU_FLAG_OK, NULL }, + + /* Outlet groups collection */ + /* pduGroupCount.1 = INTEGER: 1 */ + { "outlet.group.count", 0, 1, + ".1.3.6.1.4.1.534.7.1.1.2.1.12.1", + NULL, SU_FLAG_STATIC, NULL }, + /* pduGroupVoltage.1.1 = INTEGER: 2418 */ + { "outlet.group.%i.voltage", 0, 0.1, + ".1.3.6.1.4.1.534.7.1.3.1.1.5.1.%i", + NULL, SU_OUTLET_GROUP, NULL }, + /* pduGroupCurrent.1.1 = INTEGER: 0 */ + { "outlet.group.%i.current", 0, 1, + ".1.3.6.1.4.1.534.7.1.3.1.1.12.1.%i", + NULL, SU_OUTLET_GROUP, NULL }, + + /* Outlet collection */ + /* pduOutletCount.1 = INTEGER: 6 */ + { "outlet.count", 0, 1, + ".1.3.6.1.4.1.534.7.1.1.2.1.13.1", + NULL, SU_FLAG_OK, NULL }, + /* pduControllable.1 = INTEGER: 1 */ + { "outlet.switchable", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.1.2.1.10.1", + "no", SU_FLAG_STATIC, + &eaton_nlogic_unit_switchability_info[0] }, + /* pduOutletControlSwitchable.1.1 = INTEGER: 2 */ + { "outlet.%i.switchable", ST_FLAG_RW |ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.5.2.1.8.1.%i", + "no", SU_OUTLET, + &eaton_nlogic_unit_switchability_info[0] }, + /* pduOutletControlStatus.1.1 = INTEGER: 2 */ + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.5.2.1.1.1.%i", + NULL, SU_OUTLET, + &eaton_nlogic_outlet_status_info[0] }, + /* pduOutletName.1.1 = STRING: "OUTLET 1" */ + { "outlet.%i.name", ST_FLAG_RW |ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.5.1.1.2.1.%i", + NULL, SU_OUTLET, NULL }, + /* pduOutletType.1.1 = INTEGER: 2 */ + { "outlet.%i.type", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.7.1.5.1.1.3.1.%i", + "unknown", SU_FLAG_STATIC | SU_OUTLET, + &eaton_nlogic_outlet_type_info[0] }, + /* pduOutletCurrentRating.1.1 = INTEGER: 1600 */ + { "outlet.%i.current.nominal", 0, 0.01, + ".1.3.6.1.4.1.534.7.1.5.1.1.4.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pduOutletCurrent.1.1 = INTEGER: 0 */ + { "outlet.%i.current", 0, 0.01, + ".1.3.6.1.4.1.534.7.1.5.1.1.5.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pduOutletCurrentPercentLoad.1.1 = INTEGER: 0 */ + { "outlet.%i.load", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.1.1.11.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pduOutletVA.1.1 = INTEGER: 0 */ + { "outlet.%i.power", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.1.1.12.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pduOutletWatts.1.1 = INTEGER: 0 */ + { "outlet.%i.realpower", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.1.1.13.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + + /* instant commands. */ + /* pduOutletControlCommand.1.1 = INTEGER: 2 */ + { "outlet.%i.load.off", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + "1", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + "2", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.cycle", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + "5", SU_TYPE_CMD | SU_OUTLET, NULL }, + + /* Per-outlet shutdown / startup delay (configuration point, not the timers) + * (by default each output socket startup is delayed by its number in seconds) + */ + /* pduOutletControlShutoffDelay.1.1 = INTEGER: 0 */ + { "outlet.%i.delay.shutdown", ST_FLAG_RW, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.9.1.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + /* pduOutletControlSequenceDelay.1.1 = INTEGER: 0 */ + { "outlet.%i.delay.start", ST_FLAG_RW, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.6.1.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + /* FIXME: need RFC! */ + /* pduOutletControlRebootOffTime.1.1 = INTEGER: 5 */ + { "outlet.%i.delay.reboot", ST_FLAG_RW, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.7.1.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL }, + + +#if 0 + /* FIXME: how to deal with these? + Delays are in 1 OID and command in another. + These versions should take the delay, set the related OID (need the outlet index, so miss context!) and then call the command */ + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "outlet.%i.load.off.delay", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + set "outlet.%i.delay.shutdown" + set itself to delayedOff (3) + // &eaton_nlogic_outlet_delayed_off_info[0] + { "outlet.%i.load.on.delay", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + set "outlet.%i.delay.start" + set itself to delayedOn (4), + // &eaton_nlogic_outlet_delayed_on_info[0] + { "outlet.%i.load.cycle.delay", 0, 1, + ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + set "outlet.%i.delay.start" + set itself to delayedReboot (6), + // &eaton_nlogic_outlet_delayed_reboot_info[0] + + + /* pduIPv4Address.1 = IpAddress: 192.168.1.55 */ + { "unmapped.pduIPv4Address", 0, 1, ".1.3.6.1.4.1.534.7.1.1.2.1.15.1", NULL, SU_FLAG_OK, NULL }, + /* pduIPv6Address.1 = STRING: "FE80::CA45:44FF:FE30:9414" */ + { "unmapped.pduIPv6Address", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.1.2.1.16.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigSsh.1 = INTEGER: 1 */ + { "unmapped.pduConfigSsh", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigFtps.1 = INTEGER: 1 */ + { "unmapped.pduConfigFtps", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigHttp.1 = INTEGER: 0 */ + { "unmapped.pduConfigHttp", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigHttps.1 = INTEGER: 1 */ + { "unmapped.pduConfigHttps", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigIPv4IPv6Switch.1 = INTEGER: 3 */ + { "unmapped.pduConfigIPv4IPv6Switch", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigRedfishAPI.1 = INTEGER: 0 */ + { "unmapped.pduConfigRedfishAPI", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigOledDispalyOrientation.1 = INTEGER: 1 */ + { "unmapped.pduConfigOledDispalyOrientation", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigEnergyReset.1 = INTEGER: 1 */ + { "unmapped.pduConfigEnergyReset", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigNetworkManagementCardReset.1 = INTEGER: 0 */ + { "unmapped.pduConfigNetworkManagementCardReset", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.10.1", NULL, SU_FLAG_OK, NULL }, + +/* pduConfigDaisyChainStatus.1 = INTEGER: 0 */ +{ "unmapped.pduConfigDaisyChainStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.11.1", NULL, SU_FLAG_OK, NULL }, + + /* pduInputFrequencyStatus.1 = INTEGER: 1 */ + { "unmapped.pduInputFrequencyStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerVA.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerWatts.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputTotalEnergy.1 = INTEGER: 0 */ + { "unmapped.pduInputTotalEnergy", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerWattHourTimer.1 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduInputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.2.1.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputResettableEnergy.1 = INTEGER: 0 */ + { "unmapped.pduInputResettableEnergy", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerFactor.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerVAR.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseIndex.1.1 = INTEGER: 1 */ + { "unmapped.pduInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseIndex.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pduInputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + + /* pduInputPhaseVoltage.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltage", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltage.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltage", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThStatus.1.1 = INTEGER: 5 */ + { "unmapped.pduInputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerWarning.1.1 = INTEGER: 1900 */ + { "unmapped.pduInputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerCritical.1.1 = INTEGER: 1800 */ + { "unmapped.pduInputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperWarning.1.1 = INTEGER: 2150 */ + { "unmapped.pduInputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperCritical.1.1 = INTEGER: 2250 */ + { "unmapped.pduInputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pduInputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentRating.1.1 = INTEGER: 2400 */ + { "unmapped.pduInputPhaseCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentRating.1.2 = INTEGER: 2400 */ + { "unmapped.pduInputPhaseCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentRating.1.3 = INTEGER: 2400 */ + { "unmapped.pduInputPhaseCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrent.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrent", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.11.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrent.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrent", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.11.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrent.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrent", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.11.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduInputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.12.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.12.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.12.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.13.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.13.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.13.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.14.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.14.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.14.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperWarning.1.1 = INTEGER: 2100 */ + { "unmapped.pduInputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.15.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.15.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.15.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperCritical.1.1 = INTEGER: 2400 */ + { "unmapped.pduInputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.16.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.16.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.16.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentPercentLoad.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.17.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentPercentLoad.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.17.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentPercentLoad.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.17.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pduInputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.18.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.18.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.18.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVA.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVA.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.19.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVA.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.19.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWatts.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWatts.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.20.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWatts.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.20.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHour.1.1 = INTEGER: 30 */ + { "unmapped.pduInputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.21.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHour.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.21.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHour.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.21.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHourTimer.1.1 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduInputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.2.2.1.22.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHourTimer.1.2 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduInputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.2.2.1.22.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerWattHourTimer.1.3 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduInputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.2.2.1.22.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerFactor.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.23.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerFactor.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.23.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerFactor.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.23.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVAR.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.24.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVAR.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.24.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhasePowerVAR.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.24.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThResetThld.1.1 = INTEGER: 20 */ + { "unmapped.pduInputPhaseVoltageThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.25.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThResetThld.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.25.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThResetThld.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.25.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThChangeDelay.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.26.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThChangeDelay.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.26.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThChangeDelay.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.26.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThCtrl.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.27.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.27.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseVoltageThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.27.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThResetThld.1.1 = INTEGER: 100 */ + { "unmapped.pduInputPhaseCurrentThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.28.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThResetThld.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.28.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThResetThld.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.28.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThChangeDelay.1.1 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.29.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThChangeDelay.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.29.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThChangeDelay.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.29.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThCtrl.1.1 = INTEGER: 12 */ + { "unmapped.pduInputPhaseCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.30.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.30.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduInputPhaseCurrentThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduInputPhaseCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.30.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThLowerWarning.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.31.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThLowerCritical.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.32.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThUpperWarning.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.33.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThUpperCritical.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.34.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThResetThld.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.35.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThChangeDelay.1 = INTEGER: 0 */ + { "unmapped.pduInputPowerThresholdThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.36.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputPowerThresholdThCtrl.1 = INTEGER: 15 */ + { "unmapped.pduInputPowerThresholdThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.37.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputEnergyThresholdThUpperWarning.1 = INTEGER: 2147483 */ + { "unmapped.pduInputEnergyThresholdThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.38.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputEnergyThresholdThUpperCritical.1 = INTEGER: 2147483 */ + { "unmapped.pduInputEnergyThresholdThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.39.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputEnergyThresholdThResetThld.1 = INTEGER: 0 */ + { "unmapped.pduInputEnergyThresholdThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.40.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputEnergyThresholdThChangeDelay.1 = INTEGER: 0 */ + { "unmapped.pduInputEnergyThresholdThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.41.1", NULL, SU_FLAG_OK, NULL }, + /* pduInputEnergyThresholdThCtrl.1 = INTEGER: 3 */ + { "unmapped.pduInputEnergyThresholdThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.2.2.1.42.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.1 = INTEGER: 1 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.2 = INTEGER: 2 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.3 = INTEGER: 3 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.4 = INTEGER: 4 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.5 = INTEGER: 5 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.6 = INTEGER: 6 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.7 = INTEGER: 7 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.8 = INTEGER: 8 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.9 = INTEGER: 9 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.10 = INTEGER: 10 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.11 = INTEGER: 11 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupIndex.1.12 = INTEGER: 12 */ + { "unmapped.pduGroupIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.1.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.1 = Hex-STRING: 42 31 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.2 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.3 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.4 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.5 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.6 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.7 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.8 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.9 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.10 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.11 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupName.1.12 = Hex-STRING: 00 */ + { "unmapped.pduGroupName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.2.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.1 = INTEGER: 5 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupType.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.3.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageMeasType.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.4.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pduGroupVoltageThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThStatus.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.6.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.7.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.8.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.9.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.10.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.1 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.2 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.3 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.4 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.5 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.6 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.7 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.8 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.9 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.10 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.11 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdugroupCurrentRating.1.12 = INTEGER: 0 */ + { "unmapped.pdugroupCurrentRating", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.11.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pduGroupCurrentThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThStatus.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.13.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.14.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.15.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.16.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.17.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentPercentLoad.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.12", NULL, SU_FLAG_OK, NULL }, +/* pduGroupPowerVA.1.1 = INTEGER: 0 */ +{ "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.12", NULL, SU_FLAG_OK, NULL }, +/* pduGroupPowerWatts.1.1 = INTEGER: 0 */ +{ "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHour.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.21.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.1 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.2 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.3 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.4 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.5 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.6 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.7 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.8 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.9 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.10 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.11 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWattHourTimer.1.12 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduGroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.3.1.1.22.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.1 = INTEGER: 100 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerFactor.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.23.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVAR.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.24.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.1 = INTEGER: 6 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupOutletCount.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupOutletCount", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.25.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupBreakerStatus.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.26.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupVoltageThCtrl.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupVoltageThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.27.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.4 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.5 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.6 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.7 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.8 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.9 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.10 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.11 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduGroupCurrentThCtrl.1.12 = INTEGER: 0 */ + { "unmapped.pduGroupCurrentThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.28.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureScale.1 = INTEGER: 1 */ + { "unmapped.pduTemperatureScale", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureCount.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityCount.1 = INTEGER: 0 */ + { "unmapped.pduHumidityCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pduDoorCount.1 = INTEGER: 0 */ + { "unmapped.pduDoorCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* pduDryCount.1 = INTEGER: 0 */ + { "unmapped.pduDryCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* pduSpotCount.1 = INTEGER: 0 */ + { "unmapped.pduSpotCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pduRopeCount.1 = INTEGER: 0 */ + { "unmapped.pduRopeCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidCount.1 = INTEGER: 0 */ + { "unmapped.pduHidCount", 0, 1, ".1.3.6.1.4.1.534.7.1.4.1.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureIndex.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.1 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.2 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.3 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.4 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.5 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureName.1.6 = STRING: " " */ + { "unmapped.pduTemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.2.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.3 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.4 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.5 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureProbeStatus.1.6 = INTEGER: 1 */ + { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.6", NULL, SU_FLAG_OK, NULL }, +/* pduTemperatureValue.1.1 = INTEGER: 0 */ +{ "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThStatus.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.4 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.5 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureThCtrl.1.6 = INTEGER: 0 */ + { "unmapped.pduTemperatureThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityIndex.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.1 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.2 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.3 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.4 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.5 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityName.1.6 = STRING: " " */ + { "unmapped.pduHumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.3.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.3 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.4 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.5 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityProbeStatus.1.6 = INTEGER: 1 */ + { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.6", NULL, SU_FLAG_OK, NULL }, +/* pduHumidityValue.1.1 = INTEGER: 0 */ +{ "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThStatus.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.2 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.3 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.4 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.5 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityThCtrl.1.6 = INTEGER: 0 */ + { "unmapped.pduHumidityThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduDoorIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduDoorIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDoorIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduDoorIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDoorName.1.1 = STRING: " " */ + { "unmapped.pduDoorName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.4.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDoorName.1.2 = STRING: " " */ + { "unmapped.pduDoorName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.4.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDoorProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduDoorProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDoorProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduDoorProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDoorState.1.1 = INTEGER: 0 */ + { "unmapped.pduDoorState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDoorState.1.2 = INTEGER: 0 */ + { "unmapped.pduDoorState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.4.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDryIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduDryIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDryIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduDryIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDryName.1.1 = STRING: " " */ + { "unmapped.pduDryName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.5.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDryName.1.2 = STRING: " " */ + { "unmapped.pduDryName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.5.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDryProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduDryProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDryProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduDryProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduDryState.1.1 = INTEGER: 0 */ + { "unmapped.pduDryState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduDryState.1.2 = INTEGER: 0 */ + { "unmapped.pduDryState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.5.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduSpotIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduSpotIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduSpotIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduSpotIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduSpotName.1.1 = STRING: " " */ + { "unmapped.pduSpotName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.6.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduSpotName.1.2 = STRING: " " */ + { "unmapped.pduSpotName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.6.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduSpotProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduSpotProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduSpotProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduSpotProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduSpotState.1.1 = INTEGER: 0 */ + { "unmapped.pduSpotState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduSpotState.1.2 = INTEGER: 0 */ + { "unmapped.pduSpotState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.6.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduRopeIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduRopeIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduRopeIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduRopeIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduRopeName.1.1 = STRING: " " */ + { "unmapped.pduRopeName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.7.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduRopeName.1.2 = STRING: " " */ + { "unmapped.pduRopeName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.7.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduRopeProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduRopeProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduRopeProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduRopeProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduRopeState.1.1 = INTEGER: 0 */ + { "unmapped.pduRopeState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduRopeState.1.2 = INTEGER: 0 */ + { "unmapped.pduRopeState", 0, 1, ".1.3.6.1.4.1.534.7.1.4.7.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHIDIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduHIDIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHIDIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduHIDIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidAisle.1.1 = INTEGER: 0 */ + { "unmapped.pduHidAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidAisle.1.2 = INTEGER: 0 */ + { "unmapped.pduHidAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidHandleOperation.1.1 = INTEGER: 2 */ + { "unmapped.pduHidHandleOperation", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidHandleOperation.1.2 = INTEGER: 2 */ + { "unmapped.pduHidHandleOperation", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHIDVer.1.1 = Hex-STRING: 02 00 00 00 00 */ + { "unmapped.pduHIDVer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.1.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHIDVer.1.2 = Hex-STRING: 02 00 00 00 00 */ + { "unmapped.pduHIDVer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.1.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduMechanicalLock.1.1 = INTEGER: 2 */ + { "unmapped.pduMechanicalLock", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduMechanicalLock.1.2 = INTEGER: 2 */ + { "unmapped.pduMechanicalLock", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.1.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.1 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.2 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.3 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.4 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.5 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.6 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.7 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.8 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.9 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.10 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.11 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.12 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.13 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.14 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.15 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlIndex.1.16 = INTEGER: 0 */ + { "unmapped.pduHidControlIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.1.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.1 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.2 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.3 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.4 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.5 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.6 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.7 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.8 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.9 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.10 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.11 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.12 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.13 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.14 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.15 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlUserName.1.16 = "" */ + { "unmapped.pduHidControlUserName", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.2.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.1 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.2 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.3 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.4 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.5 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.6 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.7 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.8 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.9 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.10 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.11 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.12 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.13 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.14 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.15 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardID.1.16 = INTEGER: 0 */ + { "unmapped.pduHidControlCardID", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.3.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.1 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.2 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.3 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.4 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.5 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.6 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.7 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.8 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.9 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.10 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.11 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.12 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.13 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.14 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.15 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlTimestamp.1.16 = STRING: "2000/00/00 00:00:00" */ + { "unmapped.pduHidControlTimestamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.4.10.2.1.4.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.1 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.2 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.3 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.4 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.5 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.6 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.7 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.8 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.9 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.10 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.11 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.12 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.13 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.14 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.15 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduHidControlCardAisle.1.16 = INTEGER: 0 */ + { "unmapped.pduHidControlCardAisle", 0, 1, ".1.3.6.1.4.1.534.7.1.4.10.2.1.5.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.1 = INTEGER: 1 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.2 = INTEGER: 2 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.3 = INTEGER: 3 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.4 = INTEGER: 4 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.5 = INTEGER: 5 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.6 = INTEGER: 6 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletIndex.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletIndex", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.1.1.48", NULL, SU_FLAG_OK, NULL }, + + /* pduOutletActivePowerThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.2 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.3 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.4 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.5 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.6 = INTEGER: 1 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThStatus.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.6.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerWarning.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.7.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThLowerCritical.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.8.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperWarning.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.9.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThUpperCritical.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.10.1.48", NULL, SU_FLAG_OK, NULL }, + + /* pduOutletWh.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWh.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletWh", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.14.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.1 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.2 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.3 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.4 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.5 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.6 = Hex-STRING: 32 30 32 31 2F 30 35 2F 32 39 20 30 39 3A 30 36 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.7 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.8 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.9 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.10 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.11 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.12 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.13 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.14 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.15 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.16 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.17 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.18 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.19 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.20 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.21 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.22 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.23 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.24 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.25 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.26 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.27 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.28 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.29 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.30 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.31 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.32 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.33 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.34 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.35 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.36 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.37 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.38 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.39 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.40 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.41 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.42 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.43 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.44 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.45 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.46 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.47 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletWhTimer.1.48 = Hex-STRING: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ + { "unmapped.pduOutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.5.1.1.15.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.1 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.2 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.3 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.4 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.5 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.6 = INTEGER: 100 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletPowerFactor.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletPowerFactor", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.16.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletVAR.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletVAR", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.17.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletBranch.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletBranch", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.18.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThResetThld.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThResetThld", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.19.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.1 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.2 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.3 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.4 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.5 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.6 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThChangeDelay.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletActivePowerThChangeDelay", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.20.1.48", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.1 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.2 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.3 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.4 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.5 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.6 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.7 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.8 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.9 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.10 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.11 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.12 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.13 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.14 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.15 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.16 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.17 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.18 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.19 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.20 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.21 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.22 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.23 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.24 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.25 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.26 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.27 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.28 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.29 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.30 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.31 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.32 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.33 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.34 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.35 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.36 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.37 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.38 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.39 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.40 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.41 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.42 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.43 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.44 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.45 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.46 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.47 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletActivePowerThCtrl.1.48 = INTEGER: 15 */ + { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.48", NULL, SU_FLAG_OK, NULL }, + + +/* pduOutletControlOffCmd.1.1 = INTEGER: -1 */ +{ "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.2 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.3 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.4 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.5 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.6 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.48", NULL, SU_FLAG_OK, NULL }, +/* pduOutletControlOnCmd.1.1 = INTEGER: -1 */ +{ "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.2 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.3 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.4 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.5 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.6 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.48", NULL, SU_FLAG_OK, NULL }, +/* pduOutletControlRebootCmd.1.1 = INTEGER: -1 */ +{ "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.2 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.3 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.4 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.5 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.6 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.48", NULL, SU_FLAG_OK, NULL }, +/* pduOutletControlPowerOnState.1.1 = INTEGER: 2 */ +{ "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.2 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.3 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.4 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.5 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.6 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.7 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.7", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.8 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.8", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.9 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.9", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.10 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.10", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.11 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.11", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.12 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.12", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.13 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.13", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.14 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.14", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.15 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.15", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.16 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.16", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.17 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.17", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.18 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.18", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.19 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.19", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.20 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.20", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.21 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.21", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.22 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.22", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.23 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.23", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.24 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.24", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.25 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.25", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.26 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.26", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.27 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.27", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.28 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.28", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.29 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.29", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.30 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.30", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.31 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.31", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.32 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.32", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.33 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.33", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.34 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.34", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.35 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.35", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.36 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.36", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.37 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.37", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.38 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.38", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.39 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.39", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.40 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.40", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.41 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.41", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.42 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.42", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.43 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.43", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.44 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.44", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.45 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.45", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.46 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.46", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.47 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.47", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.48 = INTEGER: 0 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.48", NULL, SU_FLAG_OK, NULL }, + +#endif + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +}; + +mib2nut_info_t eaton_pdu_nlogic = { "eaton_pdu_nlogic", EATON_PDU_NLOGIC_MIB_VERSION, NULL, NULL, eaton_pdu_nlogic_mib, EATON_PDU_NLOGIC_SYSOID, NULL }; diff --git a/drivers/eaton-pdu-nlogic-mib.h b/drivers/eaton-pdu-nlogic-mib.h new file mode 100644 index 0000000000..7ac83ec8e2 --- /dev/null +++ b/drivers/eaton-pdu-nlogic-mib.h @@ -0,0 +1,30 @@ +/* eaton-pdu-nlogic-mib.h - subdriver to monitor eaton-pdu-nlogic SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2022 Eaton (author: Arnaud Quette ) + * + * 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 EATON_PDU_NLOGIC_MIB_H +#define EATON_PDU_NLOGIC_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t eaton_pdu_nlogic; + +#endif /* EATON_PDU_NLOGIC_MIB_H */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index ecb781598c..058e72f9e1 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -67,6 +67,7 @@ #include "eaton-ats30-mib.h" #include "emerson-avocent-pdu-mib.h" #include "hpe-pdu-mib.h" +#include "eaton-pdu-nlogic-mib.h" /* Address API change */ #if ( ! NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol ) && ( ! defined usmAESPrivProtocol ) @@ -106,6 +107,7 @@ static mib2nut_info_t *mib2nut[] = { &eaton_ats16_nm2, /* This struct comes from : eaton-ats16-nm2-mib.c */ &eaton_ats30, /* This struct comes from : eaton-ats30-mib.c */ &eaton_marlin, /* This struct comes from : eaton-mib.c */ + &eaton_pdu_nlogic, /* This struct comes from : eaton-pdu-nlogic-mib.c */ &emerson_avocent_pdu, /* This struct comes from : emerson-avocent-pdu-mib.c */ &aphel_revelation, /* This struct comes from : eaton-mib.c */ &aphel_genesisII, /* This struct comes from : eaton-mib.c */ @@ -168,7 +170,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.23" +#define DRIVER_VERSION "1.24" /* driver description structure */ upsdrv_info_t upsdrv_info = { From b6cd6c8a13934174975ce2a5f9a42da9a2ef082c Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Wed, 9 Nov 2022 13:52:32 +0100 Subject: [PATCH 0059/1232] Add eaton (nLogic) pdu in driver.list --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index f70250b469..f93ad4b825 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -376,6 +376,7 @@ "Eaton" "pdu" "5" "ePDU Managed" "" "snmp-ups" "Eaton" "pdu" "5" "ePDU Switched" "" "snmp-ups" "Eaton" "pdu" "5" "ePDU Monitored" "" "snmp-ups or netxml-ups" +"Eaton" "ups" "5" "ePDU EMSV0001" "nLogic rebranded" "snmp-ups" "Eaton" "ups" "5" "Powerware 3105" "USB" "bcmxcp_usb" # http://powerquality.eaton.com/Products-services/Backup-Power-UPS/3105-eol.aspx "Eaton" "ups" "5" "Powerware 9125" "USB card" "bcmxcp_usb" "Eaton" "ups" "5" "Powerware 9130" "" "bcmxcp or usbhid-ups" From 62a1c4569d8a9a50557478e207dde8221d758fe4 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Tue, 15 Nov 2022 14:46:02 +0100 Subject: [PATCH 0060/1232] Update eaton-pdu-nlogic-mib.c Fix a typo in data flags --- drivers/eaton-pdu-nlogic-mib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/eaton-pdu-nlogic-mib.c b/drivers/eaton-pdu-nlogic-mib.c index 125ca82029..9cf993554b 100644 --- a/drivers/eaton-pdu-nlogic-mib.c +++ b/drivers/eaton-pdu-nlogic-mib.c @@ -115,7 +115,7 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { /* pduPartNumber.1 = STRING: "EMSV0001" */ { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.1.2.1.7.1", - SU_FLAG_STATIC, SU_FLAG_OK, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* For daisychain, there is only 1 physical interface! */ /* pduMACAddress.1 = Hex-STRING: 43 38 2D 34 35 2D 34 34 2D 33 30 2D 39 34 2D 31 */ { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, From 6baeaafe7ea7b23634392ee258f0f99747a4eda1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 14:50:33 +0100 Subject: [PATCH 0061/1232] docs/nut.dict: update for nut-website::projects.txt --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index d221aa4a23..ff4a6ce0e3 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3052 utf-8 +personal_ws-1.1 en 3054 utf-8 AAS ABI ACFAIL @@ -457,7 +457,9 @@ HighBatt Hirschler Hlavinka Holger +HomeKit Homebrew +Homebridge Hoogervorst Hough Hunnox From c0b9aec321c9b551cf2786d979178dcc14c216a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 14:59:40 +0100 Subject: [PATCH 0062/1232] m4/nut_report_feature.m4: save compiler settings into "conf_nut_report_feature" too --- m4/nut_report_feature.m4 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 72667ba660..0d3e9a6540 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -29,14 +29,15 @@ AC_DEFUN([NUT_REPORT_FEATURE], AC_DEFUN([NUT_PRINT_FEATURE_REPORT], [ - cat conf_nut_report_feature - - echo "------------------" - echo "Compiler settings:" + (echo "------------------" + echo "Compiler settings:" printf 'CC \t:%s\n' "$CC" printf 'CFLAGS \t:%s\n' "$CFLAGS" printf 'CXX \t:%s\n' "$CXX" printf 'CXXFLAGS\t:%s\n' "$CXXFLAGS" printf 'CPP \t:%s\n' "$CPP" printf 'CPPFLAGS\t:%s\n' "$CPPFLAGS" + ) >> conf_nut_report_feature + + cat conf_nut_report_feature ]) From 5efb6e162a9a266333b42c2e33eeaf1de29105bc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 15:07:28 +0100 Subject: [PATCH 0063/1232] m4/nut_report_feature.m4: Rename conf_nut_report_feature artifact to config.nut_report_feature.log --- .gitignore | 2 +- m4/nut_report_feature.m4 | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 01da970982..50504e1cac 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ Makefile.in /config.h /config.cache /configure -/conf_nut_report_feature +/config.nut_report_feature.log /conf??????/ /dir.??????/ /dir?.???????/ diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 0d3e9a6540..c2e7162904 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -7,12 +7,12 @@ dnl AM_CONDITIONAL) AC_DEFUN([NUT_REPORT], [ if test -z "${nut_report_feature_flag}"; then nut_report_feature_flag="1" - ac_clean_files="${ac_clean_files} conf_nut_report_feature" - echo > conf_nut_report_feature - echo "Configuration summary:" >> conf_nut_report_feature - echo "======================" >> conf_nut_report_feature + ac_clean_files="${ac_clean_files} config.nut_report_feature.log" + echo > config.nut_report_feature.log + echo "Configuration summary:" >> config.nut_report_feature.log + echo "======================" >> config.nut_report_feature.log fi - echo "$1: $2" >> conf_nut_report_feature + echo "$1: $2" >> config.nut_report_feature.log ]) AC_DEFUN([NUT_REPORT_FEATURE], @@ -37,7 +37,7 @@ AC_DEFUN([NUT_PRINT_FEATURE_REPORT], printf 'CXXFLAGS\t:%s\n' "$CXXFLAGS" printf 'CPP \t:%s\n' "$CPP" printf 'CPPFLAGS\t:%s\n' "$CPPFLAGS" - ) >> conf_nut_report_feature + ) >> config.nut_report_feature.log - cat conf_nut_report_feature + cat config.nut_report_feature.log ]) From 2088f8d8567ad6ae90513c8ea51b6fd13657827a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 15:18:43 +0100 Subject: [PATCH 0064/1232] configure.ac: fix mis-diagnosed "--with-systemdsystemunitdir=yes was requested, but PKG_CONFIG..." when it was not requested in fact --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 50cbae59bb..7814822390 100644 --- a/configure.ac +++ b/configure.ac @@ -2475,8 +2475,8 @@ case "${systemdsystemunitdir}" in yes|auto|"") AS_IF([test x"$have_PKG_CONFIG" = xyes], [systemdsystemunitdir="`$PKG_CONFIG --variable=systemdsystemunitdir systemd 2>/dev/null`" && test -n "$systemdsystemunitdir" || systemdsystemunitdir="`$PKG_CONFIG --variable=systemdsystemunitdir libsystemd 2>/dev/null`"], - [AS_IF([test "${withval}" = yes], - [AC_MSG_ERROR([--with-systemdsystemunitdir=${withval} was requested, but PKG_CONFIG could not be queried for the system settings])]) + [AS_IF([test "${systemdsystemunitdir}" = yes], + [AC_MSG_ERROR([--with-systemdsystemunitdir=${systemdsystemunitdir} was requested, but PKG_CONFIG could not be queried for the system settings])]) systemdsystemunitdir="" ]) ;; From 5293a4504e6915cc0ad202e19d108d39b2b22bf8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 15:19:19 +0100 Subject: [PATCH 0065/1232] configure.ac: fix behavior for customized paths in systemdsystemunitdir/systemdshutdowndir/systemdtmpfilesdir --- configure.ac | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 7814822390..4f08584809 100644 --- a/configure.ac +++ b/configure.ac @@ -2484,7 +2484,8 @@ case "${systemdsystemunitdir}" in systemdsystemunitdir="" ;; *) - systemdsystemunitdir="${withval}" + AS_IF([test -d "${systemdsystemunitdir}"], [], + [AC_MSG_WARN([--with-systemdsystemunitdir='${systemdsystemunitdir}' was requested, but that location does not currently exist in build environment - just so you know...])]) ;; esac if test "${systemdsystemunitdir}" = "auto" ; then systemdsystemunitdir=""; fi @@ -2518,7 +2519,8 @@ if test -n "${systemdsystemunitdir}"; then systemdshutdowndir="" ;; *) - systemdshutdowndir="${withval}" + AS_IF([test -d "${systemdshutdowndir}"], [], + [AC_MSG_WARN([--with-systemdshutdowndir='${systemdshutdowndir}' was requested, but that location does not currently exist in build environment - just so you know...])]) ;; esac fi @@ -2549,7 +2551,8 @@ case "${systemdtmpfilesdir}" in systemdtmpfilesdir="" ;; *) - systemdtmpfilesdir="${withval}" + AS_IF([test -d "${systemdtmpfilesdir}"], [], + [AC_MSG_WARN([--with-systemdtmpfilesdir='${systemdtmpfilesdir}' was requested, but that location does not currently exist in build environment - just so you know...])]) ;; esac if test "${systemdtmpfilesdir}" = "auto" ; then systemdtmpfilesdir=""; fi From fd0eb7698ef13785744c95b251f6d82f0bff7448 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 15:46:33 +0100 Subject: [PATCH 0066/1232] m4/nut_report_feature.m4: update headings in generated config.nut_report_feature.log sections --- m4/nut_report_feature.m4 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index c2e7162904..674d168b4a 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -9,8 +9,8 @@ AC_DEFUN([NUT_REPORT], nut_report_feature_flag="1" ac_clean_files="${ac_clean_files} config.nut_report_feature.log" echo > config.nut_report_feature.log - echo "Configuration summary:" >> config.nut_report_feature.log - echo "======================" >> config.nut_report_feature.log + echo "NUT Configuration summary:" >> config.nut_report_feature.log + echo "==========================" >> config.nut_report_feature.log fi echo "$1: $2" >> config.nut_report_feature.log ]) @@ -29,8 +29,9 @@ AC_DEFUN([NUT_REPORT_FEATURE], AC_DEFUN([NUT_PRINT_FEATURE_REPORT], [ - (echo "------------------" - echo "Compiler settings:" + (echo "" + echo "NUT Compiler settings:" + echo "----------------------" printf 'CC \t:%s\n' "$CC" printf 'CFLAGS \t:%s\n' "$CFLAGS" printf 'CXX \t:%s\n' "$CXX" From 254e0cd003d07c3d31d780f82cdacf44674ae0a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 15:48:17 +0100 Subject: [PATCH 0067/1232] m4/nut_report_feature.m4, configure.ac: separate NUT_REPORT_COMPILERS from NUT_PRINT_FEATURE_REPORT --- configure.ac | 1 + m4/nut_report_feature.m4 | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4f08584809..1c16b4d57f 100644 --- a/configure.ac +++ b/configure.ac @@ -3578,4 +3578,5 @@ m4_foreach_w([SCRIPTFILE], [ AC_OUTPUT +NUT_REPORT_COMPILERS NUT_PRINT_FEATURE_REPORT diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 674d168b4a..7484aa1324 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -27,7 +27,7 @@ AC_DEFUN([NUT_REPORT_FEATURE], fi ]) -AC_DEFUN([NUT_PRINT_FEATURE_REPORT], +AC_DEFUN([NUT_REPORT_COMPILERS], [ (echo "" echo "NUT Compiler settings:" @@ -39,6 +39,9 @@ AC_DEFUN([NUT_PRINT_FEATURE_REPORT], printf 'CPP \t:%s\n' "$CPP" printf 'CPPFLAGS\t:%s\n' "$CPPFLAGS" ) >> config.nut_report_feature.log +]) +AC_DEFUN([NUT_PRINT_FEATURE_REPORT], +[ cat config.nut_report_feature.log ]) From fb5890afbc9d325576ba348f7e71d787d9d663aa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:33:05 +0100 Subject: [PATCH 0068/1232] m4/nut_report_feature.m4, configure.ac: introduce --enable-keep_nut_report_feature --- configure.ac | 4 ++++ m4/nut_report_feature.m4 | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1c16b4d57f..42df6a48d9 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,10 @@ AC_C_BIGENDIAN AC_C_INLINE AC_C_FLEXIBLE_ARRAY_MEMBER AC_C_VARARRAYS + +NUT_ARG_ENABLE([keep_nut_report_feature], + [Request that we keep config.nut_report_feature.log (normally deleted by configure script after displaying)], + [no]) dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase: NUT_COMPILER_FAMILY dnl Help find warning/error details in a wall of text (must be processed before NUT_COMPILER_FAMILY_FLAGS): diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 7484aa1324..44c6b90cb4 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -7,7 +7,12 @@ dnl AM_CONDITIONAL) AC_DEFUN([NUT_REPORT], [ if test -z "${nut_report_feature_flag}"; then nut_report_feature_flag="1" - ac_clean_files="${ac_clean_files} config.nut_report_feature.log" + dnl By (legacy) default we remove this report file + dnl For CI we want to publish its artifact + dnl Manageable by "--enable-keep_nut_report_feature" + AS_IF([test x"${nut_enable_keep_nut_report_feature-}" = xyes], + [AC_MSG_NOTICE([Will keep config.nut_report_feature.log])], + [ac_clean_files="${ac_clean_files} config.nut_report_feature.log"]) echo > config.nut_report_feature.log echo "NUT Configuration summary:" >> config.nut_report_feature.log echo "==========================" >> config.nut_report_feature.log From fa922c94004dccd91e1c9c4193146b49b0bbd266 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:38:04 +0100 Subject: [PATCH 0069/1232] m4/nut_report_feature.m4: start config.nut_report_feature.log with title, not empty line --- m4/nut_report_feature.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 44c6b90cb4..fc2077442e 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -13,8 +13,7 @@ AC_DEFUN([NUT_REPORT], AS_IF([test x"${nut_enable_keep_nut_report_feature-}" = xyes], [AC_MSG_NOTICE([Will keep config.nut_report_feature.log])], [ac_clean_files="${ac_clean_files} config.nut_report_feature.log"]) - echo > config.nut_report_feature.log - echo "NUT Configuration summary:" >> config.nut_report_feature.log + echo "NUT Configuration summary:" > config.nut_report_feature.log echo "==========================" >> config.nut_report_feature.log fi echo "$1: $2" >> config.nut_report_feature.log @@ -48,5 +47,6 @@ AC_DEFUN([NUT_REPORT_COMPILERS], AC_DEFUN([NUT_PRINT_FEATURE_REPORT], [ + echo "" cat config.nut_report_feature.log ]) From a12155bcee6dc29922cf5be4d24a352b33ba75a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:39:57 +0100 Subject: [PATCH 0070/1232] m4/nut_report_feature.m4: make config.nut_report_feature.log contents more asciidoc-friendly --- m4/nut_report_feature.m4 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index fc2077442e..42de1d453c 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -15,8 +15,9 @@ AC_DEFUN([NUT_REPORT], [ac_clean_files="${ac_clean_files} config.nut_report_feature.log"]) echo "NUT Configuration summary:" > config.nut_report_feature.log echo "==========================" >> config.nut_report_feature.log + echo "" >> config.nut_report_feature.log fi - echo "$1: $2" >> config.nut_report_feature.log + echo "* $1: $2" >> config.nut_report_feature.log ]) AC_DEFUN([NUT_REPORT_FEATURE], @@ -36,12 +37,13 @@ AC_DEFUN([NUT_REPORT_COMPILERS], (echo "" echo "NUT Compiler settings:" echo "----------------------" - printf 'CC \t:%s\n' "$CC" - printf 'CFLAGS \t:%s\n' "$CFLAGS" - printf 'CXX \t:%s\n' "$CXX" - printf 'CXXFLAGS\t:%s\n' "$CXXFLAGS" - printf 'CPP \t:%s\n' "$CPP" - printf 'CPPFLAGS\t:%s\n' "$CPPFLAGS" + echo "" + printf '* CC \t:%s\n' "$CC" + printf '* CFLAGS \t:%s\n' "$CFLAGS" + printf '* CXX \t:%s\n' "$CXX" + printf '* CXXFLAGS\t:%s\n' "$CXXFLAGS" + printf '* CPP \t:%s\n' "$CPP" + printf '* CPPFLAGS\t:%s\n' "$CPPFLAGS" ) >> config.nut_report_feature.log ]) From ca0b1b858b2f9d352b45f73940c5f84f1878ec3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:45:42 +0100 Subject: [PATCH 0071/1232] ci_build.sh: --enable-keep_nut_report_feature in CI builds --- ci_build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 21ee7014f8..83ed2936d0 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -963,6 +963,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp CONFIG_OPTS+=("PKG_CONFIG_PATH=${DEFAULT_PKG_CONFIG_PATH}") fi + CONFIG_OPTS+=("--enable-keep_nut_report_feature") CONFIG_OPTS+=("--prefix=${BUILD_PREFIX}") CONFIG_OPTS+=("--sysconfdir=${BUILD_PREFIX}/etc/nut") CONFIG_OPTS+=("--with-udev-dir=${BUILD_PREFIX}/etc/udev") @@ -1793,6 +1794,7 @@ bindings) # enable whatever is auto-detectable (except docs), and highlight # any warnings if we can. ${CONFIGURE_SCRIPT} --enable-Wcolor \ + --enable-keep_nut_report_feature \ --with-all=auto --with-cgi=auto --with-serial=auto \ --with-dev=auto --with-doc=skip \ --with-nut_monitor=auto --with-pynut=auto \ From 7702d57a7edd1c6c06ae866a4bf01553ae495014 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:50:11 +0100 Subject: [PATCH 0072/1232] scripts/Windows/build-mingw-nut.sh, ci_build.sh: --enable-keep_nut_report_feature in CI builds --- ci_build.sh | 1 + scripts/Windows/build-mingw-nut.sh | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 83ed2936d0..de842388c4 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1855,6 +1855,7 @@ cross-windows-mingw*) SOURCEMODE="out-of-tree" \ MAKEFLAGS="$PARMAKE_FLAGS" \ + KEEP_NUT_REPORT_FEATURE="true" \ ./build-mingw-nut.sh $cmd ;; diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh index 30fad9f366..bc4c3810b1 100755 --- a/scripts/Windows/build-mingw-nut.sh +++ b/scripts/Windows/build-mingw-nut.sh @@ -97,9 +97,16 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff" export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff" export LDFLAGS+=" -L/usr/$ARCH/lib/" + + KEEP_NUT_REPORT_FEATURE_FLAG="" + if [ x"${KEEP_NUT_REPORT_FEATURE-}" = xtrue ]; then + KEEP_NUT_REPORT_FEATURE_FLAG="--enable-keep_nut_report_feature" + fi + # Note: installation prefix here is "/" and desired INSTALL_DIR # location is passed to `make install` as DESTDIR below. $CONFIGURE_SCRIPT $HOST_FLAG $BUILD_FLAG --prefix=/ \ + $KEEP_NUT_REPORT_FEATURE_FLAG \ PKG_CONFIG_PATH=/usr/$ARCH/lib/pkgconfig \ --without-pkg-config --with-all=auto \ --without-systemdsystemunitdir \ From 0cd657425c21a6d4458c5ee90f504c060a5a57b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 16:53:20 +0100 Subject: [PATCH 0073/1232] scripts/Windows/build-mingw-nut.sh: parameterize ARCH_PREFIX --- scripts/Windows/build-mingw-nut.sh | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh index bc4c3810b1..f4d7b28046 100755 --- a/scripts/Windows/build-mingw-nut.sh +++ b/scripts/Windows/build-mingw-nut.sh @@ -89,14 +89,18 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ BUILD_FLAG="--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE`" export CC="$ARCH-gcc" export CXX="$ARCH-g++" - export PATH="/usr/$ARCH/bin:$PATH" + + # TODO: Detect/parameterize? + # This prefix is currently valid for mingw packaging in Debian/Ubuntu. + ARCH_PREFIX="/usr/$ARCH" + export PATH="${ARCH_PREFIX}/bin:$PATH" # Note: _WIN32_WINNT>=0x0600 is needed for inet_ntop in mingw headers # and the value 0xffff is anyway forced into some components at least # by netsnmp cflags. - export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff" - export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff" - export LDFLAGS+=" -L/usr/$ARCH/lib/" + export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I${ARCH_PREFIX}/include/ -D_WIN32_WINNT=0xffff" + export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I${ARCH_PREFIX}/include/ -D_WIN32_WINNT=0xffff" + export LDFLAGS+=" -L${ARCH_PREFIX}/lib/" KEEP_NUT_REPORT_FEATURE_FLAG="" if [ x"${KEEP_NUT_REPORT_FEATURE-}" = xtrue ]; then @@ -107,7 +111,7 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ # location is passed to `make install` as DESTDIR below. $CONFIGURE_SCRIPT $HOST_FLAG $BUILD_FLAG --prefix=/ \ $KEEP_NUT_REPORT_FEATURE_FLAG \ - PKG_CONFIG_PATH=/usr/$ARCH/lib/pkgconfig \ + PKG_CONFIG_PATH=${ARCH_PREFIX}/lib/pkgconfig \ --without-pkg-config --with-all=auto \ --without-systemdsystemunitdir \ --with-pynut=app \ @@ -146,8 +150,8 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ # Cover dependencies for nut-scanner (not pre-linked) # Note: lib*snmp*.dll not listed below, it is # statically linked into binaries that use it - (cd $INSTALL_DIR/bin && cp -pf /usr/$ARCH/bin/{libgnurx,libusb,libltdl}*.dll .) || true - (cd $INSTALL_DIR/bin && cp -pf /usr/$ARCH/lib/libwinpthread*.dll .) || true + (cd $INSTALL_DIR/bin && cp -pf ${ARCH_PREFIX}/bin/{libgnurx,libusb,libltdl}*.dll .) || true + (cd $INSTALL_DIR/bin && cp -pf ${ARCH_PREFIX}/lib/libwinpthread*.dll .) || true # Steam-roll over all executables/libs we have here and copy # over resolved dependencies from the cross-build environment: From cfbdbfe624b1fbaf80abbd1298e2bab7ab0cc52e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 17:04:08 +0100 Subject: [PATCH 0074/1232] m4/nut_report_feature.m4: NUT_REPORT_COMPILERS: separate cosmetic colon from reported values --- m4/nut_report_feature.m4 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 42de1d453c..5b9fd59936 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -38,12 +38,12 @@ AC_DEFUN([NUT_REPORT_COMPILERS], echo "NUT Compiler settings:" echo "----------------------" echo "" - printf '* CC \t:%s\n' "$CC" - printf '* CFLAGS \t:%s\n' "$CFLAGS" - printf '* CXX \t:%s\n' "$CXX" - printf '* CXXFLAGS\t:%s\n' "$CXXFLAGS" - printf '* CPP \t:%s\n' "$CPP" - printf '* CPPFLAGS\t:%s\n' "$CPPFLAGS" + printf '* CC \t: %s\n' "$CC" + printf '* CFLAGS \t: %s\n' "$CFLAGS" + printf '* CXX \t: %s\n' "$CXX" + printf '* CXXFLAGS\t: %s\n' "$CXXFLAGS" + printf '* CPP \t: %s\n' "$CPP" + printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" ) >> config.nut_report_feature.log ]) From 4d46b33459d5f6f1bf7e95e7d4748ed98725683e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 17:06:27 +0100 Subject: [PATCH 0075/1232] appveyor.yml: publish config.nut_report_feature.log artifact --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 45a5b6e4bf..33f99ea2b6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -117,6 +117,9 @@ artifacts: - path: config.log name: config.log of recent build of NUT for Windows + - path: config.nut_report_feature.log + name: config.nut_report_feature.log of recent build of NUT for Windows + # Example optional cache (depends on file change): # - C:\msys64 -> appveyor.yml cache: From 2084d90508982eceb8eb0890ae577d6960b052dc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 17:24:25 +0100 Subject: [PATCH 0076/1232] drivers/eaton-pdu-nlogic-mib.c: provide default (NULL) for "device.part" --- drivers/eaton-pdu-nlogic-mib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/eaton-pdu-nlogic-mib.c b/drivers/eaton-pdu-nlogic-mib.c index 9cf993554b..cebb869529 100644 --- a/drivers/eaton-pdu-nlogic-mib.c +++ b/drivers/eaton-pdu-nlogic-mib.c @@ -115,7 +115,7 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { /* pduPartNumber.1 = STRING: "EMSV0001" */ { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.7.1.1.2.1.7.1", - SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* For daisychain, there is only 1 physical interface! */ /* pduMACAddress.1 = Hex-STRING: 43 38 2D 34 35 2D 34 34 2D 33 30 2D 39 34 2D 31 */ { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, From e304454ad4fa579936272f45ecc9db3c2084f516 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 15 Nov 2022 23:28:21 +0100 Subject: [PATCH 0077/1232] Update Makefile.am maintainer-clean the config.nut_report_feature.log --- Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.am b/Makefile.am index 978505beb2..027572ce04 100644 --- a/Makefile.am +++ b/Makefile.am @@ -212,6 +212,9 @@ endif !HAVE_CPPCHECK # Automatically generate the ChangeLog from Git logs: MAINTAINERCLEANFILES += ChangeLog +# CI builds can leave a log of selected features: +MAINTAINERCLEANFILES += config.nut_report_feature.log + # Older boundary of the ChangeLog commits range # It can be a tag ('v2.2.0'), a commit hash, a date, ... # See gitrevisions for more information on specifying ranges From 46b7a6f89529503983a4e267594177d63edf1f68 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 16 Nov 2022 15:41:49 +0100 Subject: [PATCH 0078/1232] NEWS: snmp-ups added "eaton-pdu-nlogic-mib" subdriver [#1698] --- NEWS | 2 ++ docs/nut.dict | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2a072a25e5..0a96d4e18e 100644 --- a/NEWS +++ b/NEWS @@ -104,6 +104,8 @@ https://github.com/networkupstools/nut/milestone/8 * IETF MIB mapping updated for data points where negative readings are invalid [#1558] * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] + * Added SNMP subdriver "eaton-pdu-nlogic-mib" for nLogic (rebranded Eaton) + support [#1698] * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item in the middle has a type error [#1682] diff --git a/docs/nut.dict b/docs/nut.dict index ff4a6ce0e3..bb428bfede 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3054 utf-8 +personal_ws-1.1 en 3056 utf-8 AAS ABI ACFAIL @@ -2286,6 +2286,7 @@ myprivatepassphrase mysecurityname myups myupsname +nLogic nabcd nameserver namespace @@ -2315,6 +2316,7 @@ nielchiano nitram nl nlb +nlogic nn nnn noAuthNoPriv From 751e504d026e84ff3a3d5b72aedf14c3260479eb Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Mon, 21 Nov 2022 11:49:10 +0100 Subject: [PATCH 0079/1232] Fix sysOID retrieval on non-compliant device Some SNMP agent (device) wrongly return the sysOID value as a string instead of an OID. This breaks the initial sysOID matching system of the driver Signed-off-by: Arnaud Quette --- drivers/snmp-ups.c | 125 +++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 60 deletions(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 058e72f9e1..8b808fcf76 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -170,7 +170,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.24" +#define DRIVER_VERSION "1.25" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -1885,82 +1885,87 @@ static mib2nut_info_t *match_sysoid() int i; /* Retrieve sysOID value of this device */ - if (nut_snmp_get_oid(SYSOID_OID, sysOID_buf, sizeof(sysOID_buf)) == TRUE) + if (nut_snmp_get_oid(SYSOID_OID, sysOID_buf, sizeof(sysOID_buf)) != TRUE) { - upsdebugx(1, "%s: device sysOID value = %s", __func__, sysOID_buf); + upsdebugx(2, "Can't get sysOID value (using nut_snmp_get_oid())"); + /* Fallback for non-compliant device, that returns a string and not an OID */ + if (nut_snmp_get_str(SYSOID_OID, sysOID_buf, sizeof(sysOID_buf), NULL) != TRUE) { + upsdebugx(2, "Can't get sysOID value (using nut_snmp_get_str())"); + return NULL; + } + } + + upsdebugx(1, "%s: device sysOID value = %s", __func__, sysOID_buf); + + /* Build OIDs for comparison */ + if (!read_objid(sysOID_buf, device_sysOID, &device_sysOID_len)) + { + upsdebugx(2, "%s: can't build device_sysOID %s: %s", + __func__, sysOID_buf, snmp_api_errstring(snmp_errno)); + + return NULL; + } + + /* Now, iterate on mib2nut definitions */ + for (i = 0; mib2nut[i] != NULL; i++) + { + upsdebugx(1, "%s: checking MIB %s", __func__, mib2nut[i]->mib_name); + + if (mib2nut[i]->sysOID == NULL) + continue; + + /* Clear variables */ + memset(mib2nut_sysOID, 0, sizeof(mib2nut_sysOID)); + mib2nut_sysOID_len = MAX_OID_LEN; - /* Build OIDs for comparison */ - if (!read_objid(sysOID_buf, device_sysOID, &device_sysOID_len)) + if (!read_objid(mib2nut[i]->sysOID, mib2nut_sysOID, &mib2nut_sysOID_len)) { - upsdebugx(2, "%s: can't build device_sysOID %s: %s", + upsdebugx(2, "%s: can't build OID %s: %s", __func__, sysOID_buf, snmp_api_errstring(snmp_errno)); - return NULL; + /* Try to continue anyway! */ + continue; } - /* Now, iterate on mib2nut definitions */ - for (i = 0; mib2nut[i] != NULL; i++) + /* Now compare these */ + upsdebugx(1, "%s: comparing %s with %s", __func__, sysOID_buf, mib2nut[i]->sysOID); + if (!netsnmp_oid_equals(device_sysOID, device_sysOID_len, mib2nut_sysOID, mib2nut_sysOID_len)) { - upsdebugx(1, "%s: checking MIB %s", __func__, mib2nut[i]->mib_name); + upsdebugx(2, "%s: sysOID matches MIB '%s'!", __func__, mib2nut[i]->mib_name); + /* Counter verify, using {ups,device}.model */ + snmp_info = mib2nut[i]->snmp_info; - if (mib2nut[i]->sysOID == NULL) + if (snmp_info == NULL) { + upsdebugx(0, "%s: WARNING: snmp_info is not initialized " + "for mapping table entry #%d \"%s\"", + __func__, i, mib2nut[i]->mib_name + ); continue; + } + else if (snmp_info[0].info_type == NULL) { + upsdebugx(1, "%s: WARNING: snmp_info is empty " + "for mapping table entry #%d \"%s\"", + __func__, i, mib2nut[i]->mib_name); + } - /* Clear variables */ - memset(mib2nut_sysOID, 0, sizeof(mib2nut_sysOID)); - mib2nut_sysOID_len = MAX_OID_LEN; - - if (!read_objid(mib2nut[i]->sysOID, mib2nut_sysOID, &mib2nut_sysOID_len)) + if (match_model_OID() != TRUE) { - upsdebugx(2, "%s: can't build OID %s: %s", - __func__, sysOID_buf, snmp_api_errstring(snmp_errno)); - - /* Try to continue anyway! */ + upsdebugx(2, "%s: testOID provided and doesn't match MIB '%s'!", __func__, mib2nut[i]->mib_name); + snmp_info = NULL; continue; } + else + upsdebugx(2, "%s: testOID provided and matches MIB '%s'!", __func__, mib2nut[i]->mib_name); - /* Now compare these */ - upsdebugx(1, "%s: comparing %s with %s", __func__, sysOID_buf, mib2nut[i]->sysOID); - if (!netsnmp_oid_equals(device_sysOID, device_sysOID_len, mib2nut_sysOID, mib2nut_sysOID_len)) - { - upsdebugx(2, "%s: sysOID matches MIB '%s'!", __func__, mib2nut[i]->mib_name); - /* Counter verify, using {ups,device}.model */ - snmp_info = mib2nut[i]->snmp_info; - - if (snmp_info == NULL) { - upsdebugx(0, "%s: WARNING: snmp_info is not initialized " - "for mapping table entry #%d \"%s\"", - __func__, i, mib2nut[i]->mib_name - ); - continue; - } - else if (snmp_info[0].info_type == NULL) { - upsdebugx(1, "%s: WARNING: snmp_info is empty " - "for mapping table entry #%d \"%s\"", - __func__, i, mib2nut[i]->mib_name); - } - - if (match_model_OID() != TRUE) - { - upsdebugx(2, "%s: testOID provided and doesn't match MIB '%s'!", __func__, mib2nut[i]->mib_name); - snmp_info = NULL; - continue; - } - else - upsdebugx(2, "%s: testOID provided and matches MIB '%s'!", __func__, mib2nut[i]->mib_name); - - return mib2nut[i]; - } + return mib2nut[i]; } - - /* Yell all to call for user report */ - upslogx(LOG_ERR, "No matching MIB found for sysOID '%s'!\n" \ - "Please report it to NUT developers, with an 'upsc' output for your device.\n" \ - "Going back to the classic MIB detection method.", - sysOID_buf); } - else - upsdebugx(2, "Can't get sysOID value"); + + /* Yell all to call for user report */ + upslogx(LOG_ERR, "No matching MIB found for sysOID '%s'!\n" \ + "Please report it to NUT developers, with an 'upsc' output for your device.\n" \ + "Going back to the classic MIB detection method.", + sysOID_buf); return NULL; } From 6c275de3ef3a3034938f80f0b61b4b61e2d0d064 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 21 Nov 2022 15:53:44 +0100 Subject: [PATCH 0080/1232] NEWS: update for snmp-ups fix with wrong sysOID responses [#1710] --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 0a96d4e18e..e649dca063 100644 --- a/NEWS +++ b/NEWS @@ -101,6 +101,8 @@ https://github.com/networkupstools/nut/milestone/8 and MacOS on CircleCI [#1552] - snmp-ups updates: + * Fixed detection for device agents which wrongly return the sysOID value + as a string instead of an OID [#1710] * IETF MIB mapping updated for data points where negative readings are invalid [#1558] * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] From faa85e262d072798f89347526bdebc05147cab14 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Tue, 22 Nov 2022 16:49:33 +0100 Subject: [PATCH 0081/1232] snmp-ups: add support for HPE G2 Metered & Switched PDU This support is unitary (no daisychain support yet). Also note that, due to SNMP v1 implementation limitations on this device, you should prefer SNMP v3 to get both read and write rights Signed-off-by: Arnaud Quette --- data/driver.list.in | 1 + drivers/Makefile.am | 4 +- drivers/hpe-pdu3-cis-mib.c | 1732 ++++++++++++++++++++++++++++++++++++ drivers/hpe-pdu3-cis-mib.h | 30 + drivers/snmp-ups.c | 4 +- 5 files changed, 1768 insertions(+), 3 deletions(-) create mode 100644 drivers/hpe-pdu3-cis-mib.c create mode 100644 drivers/hpe-pdu3-cis-mib.h diff --git a/data/driver.list.in b/data/driver.list.in index f93ad4b825..5a742bee4d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -506,6 +506,7 @@ "HP" "pdu" "1" "HP3488 Switch/Control Unit" "" "powerman-pdu (experimental)" "HPE" "pdu" "5" "Various (SNMP mode)" "" "snmp-ups" +"HPE" "pdu" "5" "G2 Metered & Switched PDU" "" "snmp-ups" "Huawei" "ups" "4" "UPS5000-E" "" "snmp-ups" "Huawei" "ups" "3" "UPS2000-G and UPS2000-A series" "MODBUS (USB with Linux 5.12+, or Serial RS-232)" "huawei-ups2000" # https://github.com/networkupstools/nut/issues/1066 https://github.com/networkupstools/nut/pull/1198 https://github.com/networkupstools/nut/pull/954 https://github.com/networkupstools/nut/issues/1017 diff --git a/drivers/Makefile.am b/drivers/Makefile.am index cb75d4b297..24752ab9c2 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -239,7 +239,7 @@ snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ eaton-pdu-pulizzi-mib.c eaton-pdu-revelation-mib.c eaton-pdu-nlogic-mib.c \ eaton-ats16-nmc-mib.c eaton-ats16-nm2-mib.c apc-ats-mib.c eaton-ats30-mib.c \ emerson-avocent-pdu-mib.c \ - hpe-pdu-mib.c huawei-mib.c \ + hpe-pdu-mib.c hpe-pdu3-cis-mib.c huawei-mib.c \ ietf-mib.c \ mge-mib.c \ netvision-mib.c \ @@ -341,7 +341,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi 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 \ apc-pdu-mib.h apc-epdu-mib.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 legrand-hid.h \ - hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h eaton-pdu-nlogic-mib.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 # Define a dummy library so that Automake builds rules for the # corresponding object files. This library is not actually built, diff --git a/drivers/hpe-pdu3-cis-mib.c b/drivers/hpe-pdu3-cis-mib.c new file mode 100644 index 0000000000..1c9bf12d72 --- /dev/null +++ b/drivers/hpe-pdu3-cis-mib.c @@ -0,0 +1,1732 @@ +/* hpe-pdu3-cis-mib.c - subdriver to monitor HPE_PDU_CIS SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2022 Eaton (author: Arnaud Quette ) + * + * 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 "hpe-pdu3-cis-mib.h" + +#define HPE_PDU3_CIS_MIB_VERSION "0.1" + +#define HPE_PDU3_CIS_SYSOID ".1.3.6.1.4.1.232.165.11" +#define HPE_PDU3_OID_MODEL_NAME ".1.3.6.1.4.1.232.165.11.1.2.1.3.1" + +static info_lkp_t hpe_cis_unit_switchability_info[] = { + { 1, "yes", NULL, NULL }, + { 2, "no", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t hpe_cis_outlet_group_type_info[] = { + { 2, "breaker1pole", NULL, NULL }, + { 3, "breaker2pole", NULL, NULL }, + { 4, "breaker3pole", NULL, NULL }, + { 5, "outlet-section", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +/* Note: same as marlin_outlet_type_info + i5-20R */ +/* and to eaton_nlogic_outlet_type_info - few entries */ +static info_lkp_t hpe_cis_outlet_type_info[] = { + { 1, "iecC13", NULL, NULL }, + { 2, "iecC19", NULL, NULL }, + { 10, "uk", NULL, NULL }, + { 11, "french", NULL, NULL }, + { 12, "schuko", NULL, NULL }, + { 20, "nema515", NULL, NULL }, + { 21, "nema51520", NULL, NULL }, + { 22, "nema520", NULL, NULL }, + { 23, "nemaL520", NULL, NULL }, + { 24, "nemaL530", NULL, NULL }, + { 25, "nema615", NULL, NULL }, + { 26, "nema620", NULL, NULL }, + { 27, "nemaL620", NULL, NULL }, + { 28, "nemaL630", NULL, NULL }, + { 29, "nemaL715", NULL, NULL }, + { 30, "rf203p277", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +/* Same as eaton_nlogic_outlet_status_info */ +static info_lkp_t hpe_cis_outlet_status_info[] = { + { 1, "off", NULL, NULL }, + { 2, "on", NULL, NULL }, + { 3, "pendingOff", NULL, NULL }, /* transitional status */ + { 4, "pendingOn", NULL, NULL }, /* transitional status */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t hpe_cis_outlet_switchability_info[] = { + { 1, "yes", NULL, NULL }, /* switchable */ + { 2, "no", NULL, NULL }, /* notSwitchable */ + { 0, NULL, NULL, NULL } +}; + +/* HPE_PDU_CIS Snmp2NUT lookup table */ +static snmp_info_t hpe_pdu3_cis_mib[] = { + +/* standard MIB items; if the vendor MIB contains better OIDs for + * this (e.g. with daisy-chain support), consider adding those here + */ + /* Device collection */ + { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL }, + { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL }, + { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, + /* pdu3NumberPDU.0 = INTEGER: 1 (for daisychain support) */ +// { "device.count", 0, 1, ".1.3.6.1.4.1.232.165.11.1.1.0", NULL, SU_FLAG_OK, NULL }, + /* pdu3Manufacturer.1 = STRING: "HPE" */ + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.4.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* pdu3Model.1 = STRING: "230V, 32A, 7.4kVA, 50/60Hz" */ + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3FirmwareVersion.1 = STRING: "2.0.0.J" */ + { "device.firmware", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3PartNumber.1 = STRING: "P9S18A" */ + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3SerialNumber.1 = STRING: "CN09416708" */ + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3MACAddress.1 = Hex-STRING: EC EB B8 3D 78 6D */ + { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.14.1", NULL, SU_FLAG_OK, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + + /* Input collection */ + /* pdu3InputPhaseCount.1 = INTEGER: 1 */ + { "input.phases", 0, 1, + ".1.3.6.1.4.1.232.165.11.1.2.1.11.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPowerVA.1 = INTEGER: 922 */ + { "input.power", 0, 0.001, + ".1.3.6.1.4.1.232.165.11.2.1.1.4.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, + /* pdu3InputPowerWatts.1 = INTEGER: 900 */ + { "input.realpower", 0, 0.001, + ".1.3.6.1.4.1.232.165.11.2.1.1.5.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentRating.1.%i = INTEGER: 3200 */ + /* (can be instanciated by phase) */ + { "input.current.nominal", 0, 0.01, + ".1.3.6.1.4.1.232.165.11.2.2.1.10.1.1", + NULL, 0, NULL }, + /* pdu3InputPhaseCurrent.1.%i = INTEGER: 398 */ + /* (can be instanciated by phase) */ + { "input.current", 0, 0.01, + ".1.3.6.1.4.1.232.165.11.2.2.1.11.1.1", + NULL, 0, NULL }, + /* pdu3InputPhaseVoltage.1.%i = INTEGER: 2286 */ + /* (can be instanciated by phase) */ + { "input.voltage", 0, 0.1, + ".1.3.6.1.4.1.232.165.11.2.2.1.3.1.1", + NULL, 0, NULL }, + /* pdu3InputFrequency.%i = INTEGER: 500 */ + /* (can be instanciated by phase) */ + { "input.frequency", 0, 0.1, + ".1.3.6.1.4.1.232.165.11.2.1.1.2.1", + NULL, 0, NULL }, + + /* Outlet groups collection */ + /* pdu3GroupCount.1 = INTEGER: 2 */ + { "outlet.group.count", 0, 1, + ".1.3.6.1.4.1.232.165.11.1.2.1.12.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupName.1.%i = STRING: "B01" */ + { "outlet.group.%i.name", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.3.1.1.2.1.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP /*| SU_TYPE_DAISY_1*/, + NULL }, + /* pdu3GroupType.1.%i = INTEGER: 2 */ + { "outlet.group.%i.type", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.3.1.1.3.1.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP /*| SU_TYPE_DAISY_1*/, + &hpe_cis_outlet_group_type_info[0] }, + /* pdu3GroupCurrentPercentLoad.1.%i = INTEGER: 11 */ + { "outlet.group.%i.load", 0, 1.0, + ".1.3.6.1.4.1.232.165.11.3.1.1.18.1.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP /*| SU_TYPE_DAISY_1*/, NULL }, + /* pdu3GroupCurrent.1.1 = INTEGER: 187 */ + { "outlet.group.%i.current", 0, 0.01, + ".1.3.6.1.4.1.232.165.11.3.1.1.12.1.%i", + NULL, SU_OUTLET_GROUP /*| SU_TYPE_DAISY_1*/, NULL }, + /* pdu3GroupVoltage.1.%i = INTEGER: 2286 */ + { "outlet.group.%i.voltage", 0, 0.1, + ".1.3.6.1.4.1.232.165.11.3.1.1.5.1.%i", + NULL, SU_OUTLET_GROUP, NULL }, + /* pdu3GroupOutletCount.1.1 = INTEGER: 12 */ + { "outlet.group.%i.count", 0, 1, + ".1.3.6.1.4.1.232.165.11.3.1.1.25.1.1", + NULL, SU_OUTLET_GROUP /* | SU_TYPE_DAISY_1 */, NULL }, + + /* Outlet collection */ + /* pdu3OutletCount.1 = INTEGER: 24 */ + { "outlet.count", 0, 1, + ".1.3.6.1.4.1.232.165.11.1.2.1.13.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3Controllable.1 = INTEGER: 1 */ + { "outlet.switchable", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.1.2.1.10.1", + "no", SU_FLAG_STATIC, + &hpe_cis_unit_switchability_info[0] }, + + /* pdu3OutletControlStatus.1.1 = INTEGER: 2 */ + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.5.2.1.1.1.%i", + NULL, SU_OUTLET, + &hpe_cis_outlet_status_info[0] }, + /* pdu3OutletName.1.%i = STRING: "CABNIET A FAN DOOR" */ + { "outlet.%i.name", ST_FLAG_RW |ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.5.1.1.2.1.%i", + NULL, SU_OUTLET, NULL }, + /* pdu3OutletType.1.%i = INTEGER: 2 */ + { "outlet.%i.type", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.5.1.1.3.1.%i", + "unknown", SU_FLAG_STATIC | SU_OUTLET, + &hpe_cis_outlet_type_info[0] }, + /* pdu3OutletCurrentRating.1.%i = INTEGER: 2000 */ + { "outlet.%i.current.nominal", 0, 0.01, + ".1.3.6.1.4.1.232.165.11.5.1.1.4.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pdu3OutletCurrent.1.%i = INTEGER: 36 */ + { "outlet.%i.current", 0, 0.01, + ".1.3.6.1.4.1.232.165.11.5.1.1.5.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pdu3OutletCurrentPercentLoad.1.%i = INTEGER: 18 */ + { "outlet.%i.load", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.1.1.11.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pdu3OutletVA.1.%i = INTEGER: 84 */ + { "outlet.%i.power", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.1.1.12.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pdu3OutletWatts.1.%i = INTEGER: 84 */ + { "outlet.%i.realpower", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.1.1.13.1.%i", + NULL, SU_OUTLET | SU_FLAG_NEGINVALID, NULL }, + /* pdu3OutletControlSwitchable.1.%i = INTEGER: 1 */ + { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.11.5.2.1.8.1.%i", + "no", SU_OUTLET | SU_FLAG_UNIQUE | SU_TYPE_DAISY_1, + &hpe_cis_outlet_switchability_info[0] }, + + /* instant commands. */ + /* Delays handling: + * 0-n :Time in seconds until the group command is issued + * -1:Cancel a pending group-level Off/On/Reboot command */ + /* pdu3OutletControlOffCmd.1.%i = INTEGER: -1 */ + { "outlet.%i.load.off", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.2.1.%i", + "0", SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + /* pdu3OutletControlOnCmd.1.%i = INTEGER: -1 */ + { "outlet.%i.load.on", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.3.1.%i", + "0", SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + /* pdu3OutletControlRebootCmd.1.%i = INTEGER: -1 */ + { "outlet.%i.load.cycle", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.4.1.%i", + "0", SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + + +#if 0 + /* Per-outlet shutdown / startup delay (configuration point, not the timers) + * outletControlShutoffDelay.0.3 = INTEGER: 120 + * outletControlSequenceDelay.0.8 = INTEGER: 8 + * (by default each output socket startup is delayed by its number in seconds) + */ + { "outlet.%i.delay.shutdown", ST_FLAG_RW, 1, + ".1.3.6.1.4.1.534.6.6.7.6.6.1.10.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + { "outlet.%i.delay.start", ST_FLAG_RW, 1, + ".1.3.6.1.4.1.534.6.6.7.6.6.1.7.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, +#endif + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "outlet.%i.load.off.delay", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.2.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + { "outlet.%i.load.on.delay", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.3.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + { "outlet.%i.load.cycle.delay", 0, 1, + ".1.3.6.1.4.1.232.165.11.5.2.1.4.1.%i", + NULL, SU_TYPE_CMD | SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, +#if 0 + /* Per-outlet shutdown / startup timers + * outletControlOffCmd.0.1 = INTEGER: -1 + * outletControlOnCmd.0.1 = INTEGER: -1 + */ + { "outlet.%i.timer.shutdown", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.%i.%i", + NULL, SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, + { "outlet.%i.timer.start", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.6.6.1.4.%i.%i", + NULL, SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, +#endif + +#if WITH_UNMAPPED_DATA_POINTS + + /* pdu3IdentIndex.1 = INTEGER: 1 */ + { "unmapped.pdu3IdentIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3Name.1 = "" */ + { "unmapped.pdu3Name", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.2.1", NULL, SU_FLAG_OK, NULL }, + + /* pdu3FirmwareVersionTimeStamp.1 = Hex-STRING: 32 30 31 36 2F 31 31 2F 30 31 20 32 30 3A 30 38 3A 33 39 00 */ + { "unmapped.pdu3FirmwareVersionTimeStamp", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.1.2.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3Status.1 = INTEGER: 2 */ + { "unmapped.pdu3Status", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.9.1", NULL, SU_FLAG_OK, NULL }, + + /* pdu3IPv4Address.1 = IpAddress: [PDU_IP] */ + { "unmapped.pdu3IPv4Address", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.15.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3IPv6Address.1 = STRING: "FE80::EEEB:B8FF:FE3D:786D" */ + { "unmapped.pdu3IPv6Address", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.1.2.1.16.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigSsh.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigSsh", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigFtps.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigFtps", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigHttp.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigHttp", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigHttps.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigHttps", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.5.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigIPv4IPv6Switch.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigIPv4IPv6Switch", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigRedfishAPI.1 = INTEGER: 0 */ + { "unmapped.pdu3ConfigRedfishAPI", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigOledDispalyOrientation.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigOledDispalyOrientation", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.8.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigEnergyReset.1 = INTEGER: 1 */ + { "unmapped.pdu3ConfigEnergyReset", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigNetworkManagementCardReset.1 = INTEGER: 0 */ + { "unmapped.pdu3ConfigNetworkManagementCardReset", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ConfigDaisyChainStatus.1 = INTEGER: 0 */ + { "unmapped.pdu3ConfigDaisyChainStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.1.3.1.11.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputType.1 = INTEGER: 1 */ + { "unmapped.pdu3InputType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputFrequencyStatus.1 = INTEGER: 1 */ + { "unmapped.pdu3InputFrequencyStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + + /* pdu3InputTotalEnergy.1 = INTEGER: 0 */ + { "unmapped.pdu3InputTotalEnergy", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.6.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPowerWattHourTimer.1 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.2.1.1.7.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputResettableEnergy.1 = INTEGER: 0 */ + { "unmapped.pdu3InputResettableEnergy", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.8.1", NULL, SU_FLAG_OK, NULL }, +/* pdu3InputPowerFactor.1 = INTEGER: 97 */ +{ "unmapped.pdu3InputPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPowerVAR.1 = INTEGER: 197 */ + { "unmapped.pdu3InputPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.10.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseIndex.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhaseIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseIndex.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseIndex.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + + /* pdu3InputPhaseVoltageThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerWarning.1.1 = INTEGER: 1900 */ + { "unmapped.pdu3InputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerCritical.1.1 = INTEGER: 1800 */ + { "unmapped.pdu3InputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperWarning.1.1 = INTEGER: 2500 */ + { "unmapped.pdu3InputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperCritical.1.1 = INTEGER: 2600 */ + { "unmapped.pdu3InputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseVoltageThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + + /* pdu3InputPhaseCurrentThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.12.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.12.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.12.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.13.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.13.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.13.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.14.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.14.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.14.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperWarning.1.1 = INTEGER: 2200 */ + { "unmapped.pdu3InputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.15.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.15.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.15.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperCritical.1.1 = INTEGER: 2800 */ + { "unmapped.pdu3InputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.16.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.16.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.16.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentPercentLoad.1.1 = INTEGER: 124 */ + { "unmapped.pdu3InputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.17.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentPercentLoad.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.17.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhaseCurrentPercentLoad.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhaseCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.17.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pdu3InputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.18.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerMeasType.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.18.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.18.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVA.1.1 = INTEGER: 921 */ + { "unmapped.pdu3InputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVA.1.2 = INTEGER: 921 */ + { "unmapped.pdu3InputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.19.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVA.1.3 = INTEGER: 921 */ + { "unmapped.pdu3InputPhasePowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.19.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWatts.1.1 = INTEGER: 899 */ + { "unmapped.pdu3InputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWatts.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.20.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWatts.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.20.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHour.1.1 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.21.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHour.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.21.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHour.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.21.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHourTimer.1.1 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3InputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.2.2.1.22.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHourTimer.1.2 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3InputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.2.2.1.22.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerWattHourTimer.1.3 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3InputPhasePowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.2.2.1.22.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerFactor.1.1 = INTEGER: 97 */ + { "unmapped.pdu3InputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.23.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerFactor.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.23.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerFactor.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.23.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVAR.1.1 = INTEGER: 195 */ + { "unmapped.pdu3InputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.24.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVAR.1.2 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.24.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPhasePowerVAR.1.3 = INTEGER: 0 */ + { "unmapped.pdu3InputPhasePowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.2.2.1.24.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.1 = INTEGER: 1 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.2 = INTEGER: 2 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.3 = INTEGER: 3 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.4 = INTEGER: 4 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.5 = INTEGER: 5 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.6 = INTEGER: 6 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.7 = INTEGER: 7 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.8 = INTEGER: 8 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.9 = INTEGER: 9 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.10 = INTEGER: 10 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.11 = INTEGER: 11 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupIndex.1.12 = INTEGER: 12 */ + { "unmapped.pdu3GroupIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.1.1.12", NULL, SU_FLAG_OK, NULL }, + + + + + /* pdu3GroupVoltageMeasType.1.1 = INTEGER: 1 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.2 = INTEGER: 1 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageMeasType.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageMeasType", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.4.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pdu3GroupVoltageThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.2 = INTEGER: 1 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThStatus.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.6.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerWarning.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.7.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.8.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperWarning.1.%i = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.9.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3GroupVoltageThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupVoltageThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupVoltageThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.10.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.1 = INTEGER: 1600 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.2 = INTEGER: 1600 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.3 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.4 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.5 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.6 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.7 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.8 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.9 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.10 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.11 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3groupCurrentRating.1.12 = INTEGER: 0 */ + { "unmapped.pdu3groupCurrentRating", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.11.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pdu3GroupCurrentThStatus.1.%i = INTEGER: 1 */ + { "unmapped.pdu3GroupCurrentThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.13.1.%i", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerWarning.1.%i = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.14.1.%i", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.15.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.1 = INTEGER: 1100 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.2 = INTEGER: 1100 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperWarning.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.16.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.1 = INTEGER: 1400 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.2 = INTEGER: 1400 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupCurrentThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupCurrentThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.17.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pdu3GroupPowerVA.1.1 = INTEGER: 430 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.2 = INTEGER: 530 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVA.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVA", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.19.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.1 = INTEGER: 422 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.2 = INTEGER: 512 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWatts.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWatts", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.20.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.1 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.2 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHour.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.21.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.1 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.2 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.3 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.4 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.5 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.6 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.7 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.8 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.9 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.10 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.11 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerWattHourTimer.1.12 = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.3.1.1.22.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.1 = INTEGER: 98 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.2 = INTEGER: 97 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerFactor.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.23.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.1 = INTEGER: 43 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.2 = INTEGER: 36 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupPowerVAR.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.24.1.12", NULL, SU_FLAG_OK, NULL }, + + /* pdu3GroupBreakerStatus.1.1 = INTEGER: 2 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.2 = INTEGER: 2 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.3 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.4 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.5 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.6 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.7 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.8 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.9 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.10 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.11 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3GroupBreakerStatus.1.12 = INTEGER: 0 */ + { "unmapped.pdu3GroupBreakerStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.3.1.1.26.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureScale.1 = INTEGER: 1 */ + { "unmapped.pdu3TemperatureScale", 0, 1, ".1.3.6.1.4.1.232.165.11.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureCount.1 = INTEGER: 1 */ + { "unmapped.pdu3TemperatureCount", 0, 1, ".1.3.6.1.4.1.232.165.11.4.1.1.2.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityCount.1 = INTEGER: 1 */ + { "unmapped.pdu3HumidityCount", 0, 1, ".1.3.6.1.4.1.232.165.11.4.1.1.3.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactCount.1 = INTEGER: 0 */ + { "unmapped.pdu3ContactCount", 0, 1, ".1.3.6.1.4.1.232.165.11.4.1.1.4.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureIndex.1.1 = INTEGER: 1 */ + { "unmapped.pdu3TemperatureIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureIndex.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureName.1.1 = STRING: "T" */ + { "unmapped.pdu3TemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureName.1.2 = STRING: " " */ + { "unmapped.pdu3TemperatureName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.2.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureProbeStatus.1.1 = INTEGER: 2 */ + { "unmapped.pdu3TemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pdu3TemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.3.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureValue.1.1 = INTEGER: 27 */ + { "unmapped.pdu3TemperatureValue", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureValue.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureValue", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3TemperatureThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThLowerWarning.1.1 = INTEGER: 15 */ + { "unmapped.pdu3TemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThLowerCritical.1.1 = INTEGER: 10 */ + { "unmapped.pdu3TemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThUpperWarning.1.1 = INTEGER: 30 */ + { "unmapped.pdu3TemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThUpperCritical.1.1 = INTEGER: 35 */ + { "unmapped.pdu3TemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3TemperatureThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3TemperatureThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.2.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityIndex.1.1 = INTEGER: 2 */ + { "unmapped.pdu3HumidityIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityIndex.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityName.1.1 = STRING: "RH" */ + { "unmapped.pdu3HumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityName.1.2 = STRING: " " */ + { "unmapped.pdu3HumidityName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.2", NULL, SU_FLAG_OK, NULL }, +//FIXME: missing sub MIB for ambient sensor? + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.3", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.4", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.5", NULL, SU_FLAG_OK, NULL }, + /* = STRING: " " */ + { "unmapped. = STRING: " "", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.3.1.2.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityProbeStatus.1.1 = INTEGER: 2 */ + { "unmapped.pdu3HumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pdu3HumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 1 */ + { "unmapped. = INTEGER: 1", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.3.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityValue.1.1 = INTEGER: 27 */ + { "unmapped.pdu3HumidityValue", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityValue.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityValue", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.4.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThStatus.1.1 = INTEGER: 2 */ + { "unmapped.pdu3HumidityThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThStatus.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.5.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThLowerWarning.1.1 = INTEGER: 30 */ + { "unmapped.pdu3HumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThLowerCritical.1.1 = INTEGER: 10 */ + { "unmapped.pdu3HumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThUpperWarning.1.1 = INTEGER: 60 */ + { "unmapped.pdu3HumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThUpperCritical.1.1 = INTEGER: 80 */ + { "unmapped.pdu3HumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3HumidityThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3HumidityThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* = INTEGER: 0 */ + { "unmapped. = INTEGER: 0", 0, 1, ".1.3.6.1.4.1.232.165.11.4.3.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactIndex.1.1 = INTEGER: 0 */ + { "unmapped.pdu3ContactIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactIndex.1.2 = INTEGER: 0 */ + { "unmapped.pdu3ContactIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactName.1.1 = STRING: " " */ + { "unmapped.pdu3ContactName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.4.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactName.1.2 = STRING: " " */ + { "unmapped.pdu3ContactName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.4.4.1.2.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactProbeStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3ContactProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactProbeStatus.1.2 = INTEGER: 1 */ + { "unmapped.pdu3ContactProbeStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.3.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactState.1.1 = INTEGER: 0 */ + { "unmapped.pdu3ContactState", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3ContactState.1.2 = INTEGER: 0 */ + { "unmapped.pdu3ContactState", 0, 1, ".1.3.6.1.4.1.232.165.11.4.4.1.4.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.1 = INTEGER: 1 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.2 = INTEGER: 2 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.3 = INTEGER: 3 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.4 = INTEGER: 4 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.5 = INTEGER: 5 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.6 = INTEGER: 6 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.7 = INTEGER: 7 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.8 = INTEGER: 8 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.9 = INTEGER: 9 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.10 = INTEGER: 10 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.11 = INTEGER: 11 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.12 = INTEGER: 12 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.13 = INTEGER: 13 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.14 = INTEGER: 14 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.15 = INTEGER: 15 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.16 = INTEGER: 16 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.17 = INTEGER: 17 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.18 = INTEGER: 18 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.19 = INTEGER: 19 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.20 = INTEGER: 20 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.21 = INTEGER: 21 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.22 = INTEGER: 22 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.23 = INTEGER: 23 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.24 = INTEGER: 24 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletIndex.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.1.1.48", NULL, SU_FLAG_OK, NULL }, + + + /* pdu3OutletActivePowerThStatus.1.1 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.2 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.3 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.4 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.5 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.6 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.7 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.8 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.9 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.10 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.11 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.12 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.13 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.14 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.15 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.16 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.17 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.18 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.19 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.20 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.21 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.22 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.23 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.24 = INTEGER: 1 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThStatus.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThStatus", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.6.1.48", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.1 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.4 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.5 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.6 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.7 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.8 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.9 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.10 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.11 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.12 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.13 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.14 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.15 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.16 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.17 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.18 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.19 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.20 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.21 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.22 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.23 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.24 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerWarning.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.7.1.48", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.13 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.14 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.15 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.16 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.17 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.18 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.19 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.20 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.21 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.22 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.23 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.24 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThLowerCritical.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThLowerCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.8.1.48", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.1 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.2 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.3 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.4 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.5 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.6 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.7 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.8 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.9 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.10 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.11 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.12 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.13 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.14 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.15 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.16 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.17 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.18 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.19 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.20 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.21 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.22 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.23 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.24 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperWarning.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperWarning", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.9.1.48", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.1 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.2 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.2", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.3 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.3", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.4 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.4", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.5 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.5", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.6 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.6", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.7 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.7", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.8 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.8", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.9 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.9", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.10 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.10", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.11 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.11", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.12 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.12", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.13 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.13", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.14 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.14", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.15 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.15", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.16 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.16", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.17 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.17", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.18 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.18", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.19 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.19", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.20 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.20", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.21 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.21", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.22 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.22", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.23 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.23", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.24 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.24", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.25 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.25", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.26 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.26", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.27 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.27", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.28 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.28", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.29 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.29", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.30 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.30", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.31 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.31", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.32 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.32", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.33 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.33", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.34 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.34", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.35 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.35", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.36 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.36", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.37 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.37", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.38 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.38", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.39 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.39", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.40 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.40", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.41 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.41", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.42 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.42", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.43 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.43", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.44 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.44", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.45 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.45", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.46 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.46", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.47 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.47", NULL, SU_FLAG_OK, NULL }, + /* pdu3OutletActivePowerThUpperCritical.1.48 = INTEGER: 0 */ + { "unmapped.pdu3OutletActivePowerThUpperCritical", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.10.1.48", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletWh.1.%i = INTEGER: 0 */ + { "unmapped.pdu3OutletWh", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.14.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletWhTimer.1.%i = Hex-STRING: 32 30 31 36 2F 31 30 2F 31 31 20 30 32 3A 34 36 3A 35 30 00 */ + { "unmapped.pdu3OutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.5.1.1.15.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletPowerFactor.1.%i = INTEGER: 88 */ + { "unmapped.pdu3OutletPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.16.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletVAR.1.%i = INTEGER: 2 */ + { "unmapped.pdu3OutletVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.5.1.1.17.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletControlPowerOnState.1.%i = INTEGER: 2 */ + { "unmapped.pdu3OutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.232.165.11.5.2.1.5.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletControlSequenceDelay.1.%i = INTEGER: 0 */ + { "unmapped.pdu3OutletControlSequenceDelay", 0, 1, ".1.3.6.1.4.1.232.165.11.5.2.1.6.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletControlRebootOffTime.1.%i = INTEGER: 5 */ + { "unmapped.pdu3OutletControlRebootOffTime", 0, 1, ".1.3.6.1.4.1.232.165.11.5.2.1.7.1.%i", NULL, SU_FLAG_OK, NULL }, + + /* pdu3OutletControlShutoffDelay.1.%i = INTEGER: 0 */ + { "unmapped.pdu3OutletControlShutoffDelay", 0, 1, ".1.3.6.1.4.1.232.165.11.5.2.1.9.1.%i", NULL, SU_FLAG_OK, NULL }, + +#endif /* WITH_UNMAPPED_DATA_POINTS */ + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +}; + +mib2nut_info_t hpe_pdu3_cis = { "hpe_pdu3_cis", HPE_PDU3_CIS_MIB_VERSION, NULL, HPE_PDU3_OID_MODEL_NAME, hpe_pdu3_cis_mib, HPE_PDU3_CIS_SYSOID, NULL }; diff --git a/drivers/hpe-pdu3-cis-mib.h b/drivers/hpe-pdu3-cis-mib.h new file mode 100644 index 0000000000..b6a79ac9b7 --- /dev/null +++ b/drivers/hpe-pdu3-cis-mib.h @@ -0,0 +1,30 @@ +/* hpe_pdu_cis-mib.h - subdriver to monitor HPE_PDU_CIS SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2022 Eaton (author: Arnaud Quette ) + * + * 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 HPE_PDU3_CIS_MIB_H +#define HPE_PDU3_CIS_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t hpe_pdu3_cis; + +#endif /* HPE_PDU3_CIS_MIB_H */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 8b808fcf76..f2ac76dfa4 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -67,6 +67,7 @@ #include "eaton-ats30-mib.h" #include "emerson-avocent-pdu-mib.h" #include "hpe-pdu-mib.h" +#include "hpe-pdu3-cis-mib.h" #include "eaton-pdu-nlogic-mib.h" /* Address API change */ @@ -114,6 +115,7 @@ static mib2nut_info_t *mib2nut[] = { &pulizzi_switched1, /* This struct comes from : eaton-mib.c */ &pulizzi_switched2, /* This struct comes from : eaton-mib.c */ &hpe_pdu, /* This struct comes from : hpe-pdu-mib.c */ + &hpe_pdu3_cis, /* This struct comes from : hpe-pdu3-cis-mib.c */ &huawei, /* This struct comes from : huawei-mib.c */ &mge, /* This struct comes from : mge-mib.c */ &netvision, /* This struct comes from : netvision-mib.c */ @@ -170,7 +172,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.25" +#define DRIVER_VERSION "1.26" /* driver description structure */ upsdrv_info_t upsdrv_info = { From 73fa7724e66f247dd970fd5726888d61fdbbdf9d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 22 Nov 2022 18:17:13 +0100 Subject: [PATCH 0082/1232] NEWS: added "hpe-pdu3-cis-mib" snmp-ups subdriver [#1713] --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index e649dca063..f63a970e9c 100644 --- a/NEWS +++ b/NEWS @@ -108,6 +108,10 @@ https://github.com/networkupstools/nut/milestone/8 * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] * Added SNMP subdriver "eaton-pdu-nlogic-mib" for nLogic (rebranded Eaton) support [#1698] + * Added SNMP subdriver "hpe-pdu3-cis-mib" for HPE G2 Metered & Switched PDU + initial "unitary" support (no daisychain support yet); also note that due + to SNMP v1 implementation limitations on this device, you should prefer + SNMP v3 to get both read and write rights [#1713] * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item in the middle has a type error [#1682] From c134be6c0e3b9037dba5ad72538b023a9fe5dd3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 22 Nov 2022 19:28:45 +0100 Subject: [PATCH 0083/1232] docs/nut.dict: update for #1713 --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index bb428bfede..0bbd8754d7 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3056 utf-8 +personal_ws-1.1 en 3058 utf-8 AAS ABI ACFAIL @@ -1631,6 +1631,7 @@ chunking chv ci cidr +cis clav clearalarms clearhistory @@ -1962,6 +1963,7 @@ hostnames hostsfile hotplug hotplugging +hpe href htaccess html From e50f8fe41cdaf556fb0a6d891574366d81028194 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 22 Nov 2022 19:30:32 +0100 Subject: [PATCH 0084/1232] drivers/hpe-pdu3-cis-mib.c: fix reference to WITH_UNMAPPED_DATA_POINTS This feature was only proposed, not yet implemented in main codebase --- drivers/hpe-pdu3-cis-mib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hpe-pdu3-cis-mib.c b/drivers/hpe-pdu3-cis-mib.c index 1c9bf12d72..f7f7559867 100644 --- a/drivers/hpe-pdu3-cis-mib.c +++ b/drivers/hpe-pdu3-cis-mib.c @@ -278,7 +278,7 @@ static snmp_info_t hpe_pdu3_cis_mib[] = { NULL, SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, #endif -#if WITH_UNMAPPED_DATA_POINTS +#ifdef WITH_UNMAPPED_DATA_POINTS /* pdu3IdentIndex.1 = INTEGER: 1 */ { "unmapped.pdu3IdentIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, From cce6e1ebf6899351cadb46416160f170f991935b Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Thu, 24 Nov 2022 12:39:50 +0100 Subject: [PATCH 0085/1232] snmp-ups: split Eaton pw and pxgx_ups implementation To better manage the slight nuances (especially in ups.status), between Eaton UPSs, implementation file was split in 2 files, and mib name were renamed from 'pw' to 'eaton_pw_nm2', and from 'pxgx_ups' to 'eaton_pxg_ups' Thanks to Quentin Renard (Eaton) for discovering the bug Signed-off-by: Arnaud Quette --- NEWS | 3 + UPGRADING | 3 + docs/man/snmp-ups.txt | 8 +- drivers/Makefile.am | 6 +- ...{powerware-mib.c => eaton-ups-pwnm2-mib.c} | 34 +- drivers/eaton-ups-pwnm2-mib.h | 9 + drivers/eaton-ups-pxg-mib.c | 827 ++++++++++++++++++ .../{powerware-mib.h => eaton-ups-pxg-mib.h} | 3 +- drivers/snmp-ups.c | 9 +- 9 files changed, 864 insertions(+), 38 deletions(-) rename drivers/{powerware-mib.c => eaton-ups-pwnm2-mib.c} (96%) create mode 100644 drivers/eaton-ups-pwnm2-mib.h create mode 100644 drivers/eaton-ups-pxg-mib.c rename drivers/{powerware-mib.h => eaton-ups-pxg-mib.h} (64%) diff --git a/NEWS b/NEWS index f63a970e9c..b19273a997 100644 --- a/NEWS +++ b/NEWS @@ -114,6 +114,9 @@ https://github.com/networkupstools/nut/milestone/8 SNMP v3 to get both read and write rights [#1713] * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item in the middle has a type error [#1682] + * Better manage the slight nuances (especially in ups.status) between + Eaton UPSs, and rename mibs from 'pw' to 'eaton_pw_nm2', and from + 'pxgx_ups' to 'eaton_pxg_ups' - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] diff --git a/UPGRADING b/UPGRADING index 66afe6a50d..bb019e5299 100644 --- a/UPGRADING +++ b/UPGRADING @@ -53,6 +53,9 @@ Changes from 2.8.0 to 2.8.1 or explicitly forfeit building the tool (some distro packages missed it quietly in the past) [#1560] +- snmp-ups: some subdrivers (addressed using the driver parameter `mibs`) + were renamed: 'pw' is now 'eaton_pw_nm2', and 'pxgx_ups' is 'eaton_pxg_ups' + Changes from 2.7.4 to 2.8.0 --------------------------- diff --git a/docs/man/snmp-ups.txt b/docs/man/snmp-ups.txt index 28706b01a4..a37452205e 100644 --- a/docs/man/snmp-ups.txt +++ b/docs/man/snmp-ups.txt @@ -34,12 +34,12 @@ as well as any others supporting the APC POWERNET MIB *netvision*:: Socomec Sicon UPS with Netvision Web/SNMP management card/external box -*pw*:: +*eaton_pw_nm2*:: Powerware devices with ConnectUPS SNMP cards, as well as UPSes with -Eaton Gigabit Network Cards (Network-M2) +Eaton Gigabit Network Cards (Network-M2) (renamed from pw) -*pxgx_ups*:: -Eaton devices with Power Xpert Gateway UPS Card +*eaton_pxg_ups*:: +Eaton devices with Power Xpert Gateway UPS Card (renamed from pxgx_ups) *aphel_genesisII*:: Eaton Powerware ePDU Monitored diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 24752ab9c2..c5ec006cad 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -238,12 +238,12 @@ snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ eaton-pdu-genesis2-mib.c eaton-pdu-marlin-mib.c eaton-pdu-marlin-helpers.c \ eaton-pdu-pulizzi-mib.c eaton-pdu-revelation-mib.c eaton-pdu-nlogic-mib.c \ eaton-ats16-nmc-mib.c eaton-ats16-nm2-mib.c apc-ats-mib.c eaton-ats30-mib.c \ + eaton-ups-pwnm2-mib.c eaton-ups-pxg-mib.c \ emerson-avocent-pdu-mib.c \ hpe-pdu-mib.c hpe-pdu3-cis-mib.c huawei-mib.c \ ietf-mib.c \ mge-mib.c \ netvision-mib.c \ - powerware-mib.c \ raritan-pdu-mib.c raritan-px2-mib.c \ xppc-mib.c snmp_ups_CFLAGS = $(AM_CFLAGS) @@ -329,7 +329,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi hidparser.h hidtypes.h ietf-mib.h libhid.h libshut.h nut_libusb.h liebert-hid.h \ main.h mge-hid.h mge-mib.h mge-utalk.h \ mge-xml.h microdowell.h microsol-apc.h microsol-common.h netvision-mib.h netxml-ups.h nut-ipmi.h oneac.h \ - powercom.h powerpanel.h powerp-bin.h powerp-txt.h powerware-mib.h raritan-pdu-mib.h \ + powercom.h powerpanel.h powerp-bin.h powerp-txt.h raritan-pdu-mib.h \ safenet.h serial.h snmp-ups.h solis.h tripplite.h tripplite-hid.h \ upshandler.h usb-common.h usbhid-ups.h powercom-hid.h compaq-mib.h idowell-hid.h \ apcsmart.h apcsmart_tabs.h apcsmart-old.h apcupsd-ups.h cyberpower-mib.h riello.h openups-hid.h \ @@ -340,7 +340,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h nutdrv_qx_zinto.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 \ apc-pdu-mib.h apc-epdu-mib.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 legrand-hid.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 # Define a dummy library so that Automake builds rules for the diff --git a/drivers/powerware-mib.c b/drivers/eaton-ups-pwnm2-mib.c similarity index 96% rename from drivers/powerware-mib.c rename to drivers/eaton-ups-pwnm2-mib.c index e4b0296010..29a7f1d244 100644 --- a/drivers/powerware-mib.c +++ b/drivers/eaton-ups-pwnm2-mib.c @@ -1,10 +1,10 @@ -/* powerware-mib.c - data to monitor Powerware UPS with NUT +/* eaton-ups-pwnm2-mib.c - data to monitor Powerware and Eaton NM2 UPS with NUT * (using MIBs described in stdupsv1.mib and Xups.mib) * * Copyright (C) * 2005-2006 Olli Savia * 2005-2006 Niels Baggesen - * 2015-2019 Eaton (author: Arnaud Quette ) + * 2015-2022 Eaton (author: Arnaud Quette ) * * 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,27 +23,17 @@ * */ -#include "powerware-mib.h" +#include "eaton-ups-pwnm2-mib.h" #if WITH_SNMP_LKP_FUN /* FIXME: shared helper code, need to be put in common */ #include "eaton-pdu-marlin-helpers.h" #endif -#define PW_MIB_VERSION "0.104" - -/* TODO: more sysOID and MIBs support: - * - * Powerware UPS (Ingrasys X-SLOT and BD-SLOT): ".1.3.6.1.4.1.534.1" - * Powerware PXGX cards: ".1.3.6.1.4.1.534.2.12" - * PXGX 2000 cards (UPS): Get xupsIdentModel (".1.3.6.1.4.1.534.1.1.2.0") - * PXGX 1000 cards (PDU/RPP/RPM): Get pduNumPanels ".1.3.6.1.4.1.534.6.6.4.1.1.1.4.0" - */ +#define PW_MIB_VERSION "0.105" /* Powerware UPS (Ingrasys X-SLOT and BD-SLOT) * Eaton Gigabit Network Card (Genepi) */ #define POWERWARE_SYSOID ".1.3.6.1.4.1.534.1" -/* Powerware UPS newer PXGX UPS cards (BladeUPS, ...) */ -#define EATON_PXGX_SYSOID ".1.3.6.1.4.1.534.2.12" /* SNMP OIDs set */ #define PW_OID_MFR_NAME "1.3.6.1.4.1.534.1.1.1.0" /* XUPS-MIB::xupsIdentManufacturer.0 */ @@ -129,16 +119,11 @@ static info_lkp_t pw_pwr_info[] = { { 8, "OL" /* parallel capacity */, NULL, NULL }, { 9, "OL" /* parallel redundancy */, NULL, NULL }, { 10, "OL" /* high efficiency */, NULL, NULL }, - /* Extended status values */ - { 240, "OB" /* battery (0xF0) */, NULL, NULL }, - { 100, "BYPASS" /* maintenanceBypass (0x64) */, NULL, NULL }, - { 96, "BYPASS" /* Bypass (0x60) */, NULL, NULL }, - { 81, "OL" /* high efficiency (0x51) */, NULL, NULL }, - { 80, "OL" /* normal (0x50) */, NULL, NULL }, - { 64, "OL" /* UPS supporting load, normal degraded mode (0x40) */, NULL, NULL }, - { 16, "OFF" /* none (0x10) */, NULL, NULL }, + { 11, "BYPASS" /* maintenanceBypass */, NULL, NULL }, + { 11, "OL" /* essMode */, NULL, NULL }, + { 0, NULL, NULL, NULL } -}; +}; /* FIXME: mapped to (experimental.)ups.type, but * should be output.source or ups.mode (need RFC) @@ -814,5 +799,4 @@ static alarms_info_t pw_alarms[] = { } ; -mib2nut_info_t powerware = { "pw", PW_MIB_VERSION, NULL, PW_OID_MODEL_NAME, pw_mib, POWERWARE_SYSOID , pw_alarms }; -mib2nut_info_t pxgx_ups = { "pxgx_ups", PW_MIB_VERSION, NULL, PW_OID_MODEL_NAME, pw_mib, EATON_PXGX_SYSOID , pw_alarms }; +mib2nut_info_t eaton_pw_nm2 = { "eaton_pw_nm2", PW_MIB_VERSION, NULL, PW_OID_MODEL_NAME, pw_mib, POWERWARE_SYSOID , pw_alarms }; diff --git a/drivers/eaton-ups-pwnm2-mib.h b/drivers/eaton-ups-pwnm2-mib.h new file mode 100644 index 0000000000..e764fa7b19 --- /dev/null +++ b/drivers/eaton-ups-pwnm2-mib.h @@ -0,0 +1,9 @@ +#ifndef EATON_UPS_PWNM2_MIB_H +#define EATON_UPS_PWNM2_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t eaton_pw_nm2; + +#endif /* EATON_UPS_PWNM2_MIB_H */ diff --git a/drivers/eaton-ups-pxg-mib.c b/drivers/eaton-ups-pxg-mib.c new file mode 100644 index 0000000000..7e27777446 --- /dev/null +++ b/drivers/eaton-ups-pxg-mib.c @@ -0,0 +1,827 @@ +/* eaton-ups-pxg-mib.c - data to monitor Eaton / Powerware PXG UPS with NUT + * (using MIBs described in stdupsv1.mib and Xups.mib) + * + * Copyright (C) + * 2005-2006 Olli Savia + * 2005-2006 Niels Baggesen + * 2015-2022 Eaton (author: Arnaud Quette ) + * + * 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 "eaton-ups-pxg-mib.h" +#if WITH_SNMP_LKP_FUN +/* FIXME: shared helper code, need to be put in common */ +#include "eaton-pdu-marlin-helpers.h" +#endif + +#define EATON_PXG_MIB_VERSION "0.105" + +/* Powerware UPS newer PXGX UPS cards (BladeUPS, ...) */ +#define EATON_PXGX_SYSOID ".1.3.6.1.4.1.534.2.12" + +/* SNMP OIDs set */ +#define PW_OID_MFR_NAME "1.3.6.1.4.1.534.1.1.1.0" /* XUPS-MIB::xupsIdentManufacturer.0 */ +#define PW_OID_MODEL_NAME "1.3.6.1.4.1.534.1.1.2.0" /* XUPS-MIB::xupsIdentModel.0 */ +#define PW_OID_FIRMREV "1.3.6.1.4.1.534.1.1.3.0" /* XUPS-MIB::xupsIdentSoftwareVersion.0 */ + +#define PW_OID_BATT_RUNTIME "1.3.6.1.4.1.534.1.2.1.0" /* XUPS-MIB::xupsBatTimeRemaining.0 */ +#define PW_OID_BATT_VOLTAGE "1.3.6.1.4.1.534.1.2.2.0" /* XUPS-MIB::xupsBatVoltage.0 */ +#define PW_OID_BATT_CURRENT "1.3.6.1.4.1.534.1.2.3.0" /* XUPS-MIB::xupsBatCurrent.0 */ +#define PW_OID_BATT_CHARGE "1.3.6.1.4.1.534.1.2.4.0" /* XUPS-MIB::xupsBatCapacity.0 */ +#define PW_OID_BATT_STATUS "1.3.6.1.4.1.534.1.2.5.0" /* XUPS-MIB::xupsBatteryAbmStatus.0 */ + +#define PW_OID_IN_FREQUENCY "1.3.6.1.4.1.534.1.3.1.0" /* XUPS-MIB::xupsInputFrequency.0 */ +#define PW_OID_IN_LINE_BADS "1.3.6.1.4.1.534.1.3.2.0" /* XUPS-MIB::xupsInputLineBads.0 */ +#define PW_OID_IN_LINES "1.3.6.1.4.1.534.1.3.3.0" /* XUPS-MIB::xupsInputNumPhases.0 */ +#define PW_OID_IN_VOLTAGE "1.3.6.1.4.1.534.1.3.4.1.2" /* XUPS-MIB::xupsInputVoltage */ +#define PW_OID_IN_CURRENT "1.3.6.1.4.1.534.1.3.4.1.3" /* XUPS-MIB::xupsInputCurrent */ +#define PW_OID_IN_POWER "1.3.6.1.4.1.534.1.3.4.1.4" /* XUPS-MIB::xupsInputWatts */ + +#define PW_OID_OUT_LOAD "1.3.6.1.4.1.534.1.4.1.0" /* XUPS-MIB::xupsOutputLoad.0 */ +#define PW_OID_OUT_FREQUENCY "1.3.6.1.4.1.534.1.4.2.0" /* XUPS-MIB::xupsOutputFrequency.0 */ +#define PW_OID_OUT_LINES "1.3.6.1.4.1.534.1.4.3.0" /* XUPS-MIB::xupsOutputNumPhases.0 */ +#define PW_OID_OUT_VOLTAGE "1.3.6.1.4.1.534.1.4.4.1.2" /* XUPS-MIB::xupsOutputVoltage */ +#define PW_OID_OUT_CURRENT "1.3.6.1.4.1.534.1.4.4.1.3" /* XUPS-MIB::xupsOutputCurrent */ +#define PW_OID_OUT_POWER "1.3.6.1.4.1.534.1.4.4.1.4" /* XUPS-MIB::xupsOutputWatts */ +#define PW_OID_POWER_STATUS "1.3.6.1.4.1.534.1.4.5.0" /* XUPS-MIB::xupsOutputSource.0 */ + +#define PW_OID_BY_FREQUENCY "1.3.6.1.4.1.534.1.5.1.0" /* XUPS-MIB::xupsBypassFrequency.0 */ +#define PW_OID_BY_LINES "1.3.6.1.4.1.534.1.5.2.0" /* XUPS-MIB::xupsBypassNumPhases.0 */ +#define PW_OID_BY_VOLTAGE "1.3.6.1.4.1.534.1.5.3.1.2" /* XUPS-MIB::xupsBypassVoltage */ + +#define PW_OID_BATTEST_START "1.3.6.1.4.1.534.1.8.1" /* XUPS-MIB::xupsTestBattery set to startTest(1) to initiate test*/ + +#define PW_OID_CONT_OFFDELAY "1.3.6.1.4.1.534.1.9.1.0" /* XUPS-MIB::xupsControlOutputOffDelay */ +#define PW_OID_CONT_ONDELAY "1.3.6.1.4.1.534.1.9.2.0" /* XUPS-MIB::xupsControlOutputOnDelay */ +#define PW_OID_CONT_OFFT_DEL "1.3.6.1.4.1.534.1.9.3" /* XUPS-MIB::xupsControlOutputOffTrapDelay */ +#define PW_OID_CONT_ONT_DEL "1.3.6.1.4.1.534.1.9.4" /* XUPS-MIB::xupsControlOutputOnTrapDelay */ +#define PW_OID_CONT_LOAD_SHED_AND_RESTART "1.3.6.1.4.1.534.1.9.6" /* XUPS-MIB::xupsLoadShedSecsWithRestart */ + +#define PW_OID_CONF_OVOLTAGE "1.3.6.1.4.1.534.1.10.1.0" /* XUPS-MIB::xupsConfigOutputVoltage.0 */ +#define PW_OID_CONF_IVOLTAGE "1.3.6.1.4.1.534.1.10.2.0" /* XUPS-MIB::xupsConfigInputVoltage.0 */ +#define PW_OID_CONF_POWER "1.3.6.1.4.1.534.1.10.3.0" /* XUPS-MIB::xupsConfigOutputWatts.0 */ +#define PW_OID_CONF_FREQ "1.3.6.1.4.1.534.1.10.4.0" /* XUPS-MIB::xupsConfigOutputFreq.0 */ + +#define PW_OID_ALARMS "1.3.6.1.4.1.534.1.7.1.0" /* XUPS-MIB::xupsAlarms */ +#define PW_OID_ALARM_OB "1.3.6.1.4.1.534.1.7.3" /* XUPS-MIB::xupsOnBattery */ +#define PW_OID_ALARM_LB "1.3.6.1.4.1.534.1.7.4" /* XUPS-MIB::xupsLowBattery */ + +#define IETF_OID_AGENTREV "1.3.6.1.2.1.33.1.1.4.0" /* UPS-MIB::upsIdentAgentSoftwareVersion.0 */ +#define IETF_OID_IDENT "1.3.6.1.2.1.33.1.1.5.0" /* UPS-MIB::upsIdentName.0 */ +#define IETF_OID_CONF_OUT_VA "1.3.6.1.2.1.33.1.9.5.0" /* UPS-MIB::upsConfigOutputVA.0 */ +#define IETF_OID_CONF_RUNTIME_LOW "1.3.6.1.2.1.33.1.9.7.0" /* UPS-MIB::upsConfigLowBattTime.0 */ +#define IETF_OID_LOAD_LEVEL "1.3.6.1.2.1.33.1.4.4.1.5" /* UPS-MIB::upsOutputPercentLoad */ +#define IETF_OID_AUTO_RESTART "1.3.6.1.2.1.33.1.8.5.0" /* UPS-MIB::upsAutoRestart */ + +/* Delay before powering off in seconds */ +#define DEFAULT_OFFDELAY 30 +/* Delay before powering on in seconds */ +#define DEFAULT_ONDELAY 20 +/* Default shutdown.return delay in seconds */ +#define DEFAULT_SHUTDOWNDELAY 0 + +static info_lkp_t pw_alarm_ob[] = { + { 1, "OB", NULL, NULL }, + { 2, "", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_alarm_lb[] = { + { 1, "LB", NULL, NULL }, + { 2, "", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_pwr_info[] = { + + { 0, "OFF" /* off */, NULL, NULL }, + { 1, "OL" /* systemNormal */, NULL, NULL }, + { 2, "OL" /* systemNormalUPSRedundant */, NULL, NULL }, + { 3, "OL" /* systemNormalNotRedundant */, NULL, NULL }, + { 4, "OB" /* systemOnDCSource*/, NULL, NULL }, + { 5, "OB LB" /* systemOnDCSourceShutdownImminent */, NULL, NULL }, + { 6, "OL" /* systemNormalBypassNotAvailable */, NULL, NULL }, + { 7, "OL" /* systemNormalOnLine */, NULL, NULL }, + { 8, "OL" /* systemNormalEnergySaverSystem */, NULL, NULL }, + { 9, "OL" /* systemNormalVMMS */, NULL, NULL }, + { 10, "OL" /* systemNormalHRS */, NULL, NULL }, + { 13, "OL OVER" /* outputOverload */, NULL, NULL }, + { 14, "OL TRIM" /* systemNormalOnBuck */, NULL, NULL }, + { 15, "OL BOOST" /* systemNormalOnBoost */, NULL, NULL }, + { 16, "BYPASS" /* onBypass */, NULL, NULL }, + { 17, "BYPASS" /* onBypassStarting */, NULL, NULL }, + { 18, "BYPASS" /* onBypassReady */, NULL, NULL }, + { 32, "BYPASS" /* onMaintenanceBypass */, NULL, NULL }, + { 33, "OL BYPASS" /* onMBSUPSOnLine */, NULL, NULL }, + { 34, "BYPASS" /* onMBSUPSOnBypass */, NULL, NULL }, + { 35, "OFF BYPASS" /* onMBSUPSOff */, NULL, NULL }, + { 36, "OB BYPASS" /* onMBSUPSOnBattery */, NULL, NULL }, + { 37, "OL" /* onMBSUPSOnLineESS */, NULL, NULL }, + { 38, "OL" /* onMBSUPSOnLineVMMS */, NULL, NULL }, + { 39, "OL" /* onMBSUPSOnLineHRS */, NULL, NULL }, + { 40, "OL" /* onMBSStarting */, NULL, NULL }, + { 41, "OL" /* onMBSReady */, NULL, NULL }, + { 48, "OFF" /* loadOff */, NULL, NULL }, + { 49, "OFF" /* loadOffStarting */, NULL, NULL }, + { 50, "OFF" /* loadOffReady */, NULL, NULL }, + { 64, "OL" /* supportingLoad */, NULL, NULL }, + { 80, "OL" /* systemNormalSP */, NULL, NULL }, + { 81, "OL" /* systemNormalEnergySaverSystemSP */, NULL, NULL }, + { 96, "BYPASS" /* systemOnBypassSP */, NULL, NULL }, + { 100, "BYPASS" /* systemOnManualMaintenanceBypassSP (0x64) */, NULL, NULL }, + { 224, "OL OVER" /* loadSegmentOverload (0x64) */, NULL, NULL }, + { 240, "OB" /* systemOnDCSourceSP */, NULL, NULL }, + { 241, "OFF" /* systemOffSP */, NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +/* FIXME: mapped to (experimental.)ups.type, but + * should be output.source or ups.mode (need RFC) + * to complement the above ups.status + * along with having ups.type as described hereafter*/ +/* FIXME: should be used by ups.mode or output.source (need RFC); + * Note: this define is not set via project options; code was hidden with + * original commit to "snmp-ups: support newer Genepi management cards"; + * un-hidden to make it "experimental.*" namespace during backporting + */ +#ifndef USE_PW_MODE_INFO +# define USE_PW_MODE_INFO 1 +#endif + +#if USE_PW_MODE_INFO +static info_lkp_t pw_mode_info[] = { + { 1, "", NULL, NULL }, + { 2, "", NULL, NULL }, + { 3, "normal", NULL, NULL }, + { 4, "", NULL, NULL }, + { 5, "", NULL, NULL }, + { 6, "", NULL, NULL }, + { 7, "", NULL, NULL }, + { 8, "parallel capacity", NULL, NULL }, + { 9, "parallel redundancy", NULL, NULL }, + { 10, "high efficiency", NULL, NULL }, + /* Extended status values, + * FIXME: check for source and completion */ + { 240, "" /* battery (0xF0) */, NULL, NULL }, + { 100, "" /* maintenanceBypass (0x64) */, NULL, NULL }, + { 96, "" /* Bypass (0x60) */, NULL, NULL }, + { 81, "high efficiency" /* high efficiency (0x51) */, NULL, NULL }, + { 80, "normal" /* normal (0x50) */, NULL, NULL }, + { 64, "" /* UPS supporting load, normal degraded mode (0x40) */, NULL, NULL }, + { 16, "" /* none (0x10) */, NULL, NULL }, + { 0, NULL, NULL, NULL } +}; +#endif /* USE_PW_MODE_INFO */ + +/* FIXME: may be standardized + * extracted from bcmxcp.c->BCMXCP_TOPOLOGY_*, Make some common definitions */ +static info_lkp_t pw_topology_info[] = { + { 0x0000, "", NULL, NULL }, /* None; use the Table of Elements */ + { 0x0010, "Off-line switcher, Single Phase", NULL, NULL }, + { 0x0020, "Line-Interactive UPS, Single Phase", NULL, NULL }, + { 0x0021, "Line-Interactive UPS, Two Phase", NULL, NULL }, + { 0x0022, "Line-Interactive UPS, Three Phase", NULL, NULL }, + { 0x0030, "Dual AC Input, On-Line UPS, Single Phase", NULL, NULL }, + { 0x0031, "Dual AC Input, On-Line UPS, Two Phase", NULL, NULL }, + { 0x0032, "Dual AC Input, On-Line UPS, Three Phase", NULL, NULL }, + { 0x0040, "On-Line UPS, Single Phase", NULL, NULL }, + { 0x0041, "On-Line UPS, Two Phase", NULL, NULL }, + { 0x0042, "On-Line UPS, Three Phase", NULL, NULL }, + { 0x0050, "Parallel Redundant On-Line UPS, Single Phase", NULL, NULL }, + { 0x0051, "Parallel Redundant On-Line UPS, Two Phase", NULL, NULL }, + { 0x0052, "Parallel Redundant On-Line UPS, Three Phase", NULL, NULL }, + { 0x0060, "Parallel for Capacity On-Line UPS, Single Phase", NULL, NULL }, + { 0x0061, "Parallel for Capacity On-Line UPS, Two Phase", NULL, NULL }, + { 0x0062, "Parallel for Capacity On-Line UPS, Three Phase", NULL, NULL }, + { 0x0102, "System Bypass Module, Three Phase", NULL, NULL }, + { 0x0122, "Hot-Tie Cabinet, Three Phase", NULL, NULL }, + { 0x0200, "Outlet Controller, Single Phase", NULL, NULL }, + { 0x0222, "Dual AC Input Static Switch Module, 3 Phase", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +/* Legacy implementation */ +static info_lkp_t pw_battery_abm_status[] = { + { 1, "CHRG", NULL, NULL }, + { 2, "DISCHRG", NULL, NULL }, +/* { 3, "Floating", NULL, NULL }, */ +/* { 4, "Resting", NULL, NULL }, */ +/* { 5, "Unknown", NULL, NULL }, */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_abm_status_info[] = { + { 1, "charging", NULL, NULL }, + { 2, "discharging", NULL, NULL }, + { 3, "floating", NULL, NULL }, + { 4, "resting", NULL, NULL }, + { 5, "unknown", NULL, NULL }, /* Undefined - ABM is not activated */ + { 6, "disabled", NULL, NULL }, /* ABM Charger Disabled */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_batt_test_info[] = { + { 1, "Unknown", NULL, NULL }, + { 2, "Done and passed", NULL, NULL }, + { 3, "Done and error", NULL, NULL }, + { 4, "In progress", NULL, NULL }, + { 5, "Not supported", NULL, NULL }, + { 6, "Inhibited", NULL, NULL }, + { 7, "Scheduled", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_yes_no_info[] = { + { 1, "yes", NULL, NULL }, + { 2, "no", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_outlet_status_info[] = { + { 1, "on", NULL, NULL }, + { 2, "off", NULL, NULL }, + { 3, "on", NULL, NULL }, /* pendingOff, transitional status */ + { 4, "off", NULL, NULL }, /* pendingOn, transitional status */ + /* { 5, "", NULL, NULL }, unknown */ + /* { 6, "", NULL, NULL }, reserved */ + { 7, "off", NULL, NULL }, /* Failed in Closed position */ + { 8, "on", NULL, NULL }, /* Failed in Open position */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_ambient_drycontacts_info[] = { + { -1, "unknown", NULL, NULL }, + { 1, "opened", NULL, NULL }, + { 2, "closed", NULL, NULL }, + { 3, "opened", NULL, NULL }, /* openWithNotice */ + { 4, "closed", NULL, NULL }, /* closedWithNotice */ + { 0, NULL, NULL, NULL } +}; + +#if WITH_SNMP_LKP_FUN +/* Note: eaton_sensor_temperature_unit_fun() is defined in eaton-pdu-marlin-helpers.c + * and su_temperature_read_fun() is in snmp-ups.c + * Future work for DMF might provide same-named routines via LUA-C gateway. + */ + +# if WITH_SNMP_LKP_FUN_DUMMY +/* Temperature unit consideration */ +const char *eaton_sensor_temperature_unit_fun(void *raw_snmp_value) { + /* snmp_value here would be a (long*) */ + NUT_UNUSED_VARIABLE(raw_snmp_value); + return "unknown"; +} +/* FIXME: please DMF, though this should be in snmp-ups.c or equiv. */ +const char *su_temperature_read_fun(void *raw_snmp_value) { + /* snmp_value here would be a (long*) */ + NUT_UNUSED_VARIABLE(raw_snmp_value); + return "dummy"; +}; +# endif /* WITH_SNMP_LKP_FUN_DUMMY */ + +static info_lkp_t pw_sensor_temperature_unit_info[] = { + { 0, "dummy", eaton_sensor_temperature_unit_fun, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_sensor_temperature_read_info[] = { + { 0, "dummy", su_temperature_read_fun, NULL }, + { 0, NULL, NULL, NULL } +}; + +#else /* if not WITH_SNMP_LKP_FUN: */ + +/* FIXME: For now, DMF codebase falls back to old implementation with static + * lookup/mapping tables for this, which can easily go into the DMF XML file. + */ +static info_lkp_t pw_sensor_temperature_unit_info[] = { + { 0, "kelvin", NULL, NULL }, + { 1, "celsius", NULL, NULL }, + { 2, "fahrenheit", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +#endif /* WITH_SNMP_LKP_FUN */ + +static info_lkp_t pw_ambient_drycontacts_polarity_info[] = { + { 0, "normal-opened", NULL, NULL }, + { 1, "normal-closed", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_ambient_drycontacts_state_info[] = { + { 0, "inactive", NULL, NULL }, + { 1, "active", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_emp002_ambient_presence_info[] = { + { 0, "unknown", NULL, NULL }, + { 2, "yes", NULL, NULL }, /* communicationOK */ + { 3, "no", NULL, NULL }, /* communicationLost */ + { 0, NULL, NULL, NULL } +}; + +/* extracted from drivers/eaton-pdu-marlin-mib.c -> marlin_threshold_status_info */ +static info_lkp_t pw_threshold_status_info[] = { + { 0, "good", NULL, NULL }, /* No threshold triggered */ + { 1, "warning-low", NULL, NULL }, /* Warning low threshold triggered */ + { 2, "critical-low", NULL, NULL }, /* Critical low threshold triggered */ + { 3, "warning-high", NULL, NULL }, /* Warning high threshold triggered */ + { 4, "critical-high", NULL, NULL }, /* Critical high threshold triggered */ + { 0, NULL, NULL, NULL } +}; + +/* extracted from drivers/eaton-pdu-marlin-mib.c -> marlin_threshold_xxx_alarms_info */ +static info_lkp_t pw_threshold_temperature_alarms_info[] = { + { 0, "", NULL, NULL }, /* No threshold triggered */ + { 1, "low temperature warning!", NULL, NULL }, /* Warning low threshold triggered */ + { 2, "low temperature critical!", NULL, NULL }, /* Critical low threshold triggered */ + { 3, "high temperature warning!", NULL, NULL }, /* Warning high threshold triggered */ + { 4, "high temperature critical!", NULL, NULL }, /* Critical high threshold triggered */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t pw_threshold_humidity_alarms_info[] = { + { 0, "", NULL, NULL }, /* No threshold triggered */ + { 1, "low humidity warning!", NULL, NULL }, /* Warning low threshold triggered */ + { 2, "low humidity critical!", NULL, NULL }, /* Critical low threshold triggered */ + { 3, "high humidity warning!", NULL, NULL }, /* Warning high threshold triggered */ + { 4, "high humidity critical!", NULL, NULL }, /* Critical high threshold triggered */ + { 0, NULL, NULL, NULL } +}; + +/* Snmp2NUT lookup table */ + +static snmp_info_t eaton_pxg_mib[] = { + + /* standard MIB items */ + { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL }, + { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL }, + { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, + + /* FIXME: miss device page! */ + /* UPS page */ + /* info_type, info_flags, info_len, OID, dfl, flags, oid2info, setvar */ + { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_MFR_NAME, "", + SU_FLAG_STATIC, NULL }, + { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_MODEL_NAME, "", + SU_FLAG_STATIC, NULL }, + /* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */ + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_FIRMREV, "", + 0, NULL }, + { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_AGENTREV, "", + 0, NULL }, + { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_IDENT, "", + SU_FLAG_STATIC, NULL }, + { "ups.load", 0, 1.0, PW_OID_OUT_LOAD, "", + 0, NULL }, + /* FIXME: should be removed in favor of output.power */ + { "ups.power", 0, 1.0, PW_OID_OUT_POWER ".1", "", + 0, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* xupsOutputWatts.1.0; Value (Integer): 300 */ + { "ups.power", 0, 1.0, "1.3.6.1.4.1.534.1.4.4.1.4.1.0", "", + 0, NULL }, + + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_POWER_STATUS, "OFF", + SU_STATUS_PWR, &pw_pwr_info[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_ALARM_OB, "", + SU_STATUS_BATT, &pw_alarm_ob[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_ALARM_LB, "", + SU_STATUS_BATT, &pw_alarm_lb[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_BATT_STATUS, "", + SU_STATUS_BATT, &pw_battery_abm_status[0] }, +#if USE_PW_MODE_INFO + /* FIXME: should be ups.mode or output.source (need RFC) */ + /* Note: this define is not set via project options; code hidden with + * commit to "snmp-ups: support newer Genepi management cards" */ + { "experimental.ups.type", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_POWER_STATUS, "", + SU_FLAG_STATIC | SU_FLAG_OK, &pw_mode_info[0] }, +#endif /* USE_PW_MODE_INFO */ + /* xupsTopologyType.0; Value (Integer): 32 */ + { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.4.1.534.1.13.1.0", "", + SU_FLAG_STATIC | SU_FLAG_OK, &pw_topology_info[0] }, + /* FIXME: should be removed in favor of their output. equivalent! */ + { "ups.realpower.nominal", 0, 1.0, PW_OID_CONF_POWER, "", + 0, NULL }, + /* FIXME: should be removed in favor of output.power.nominal */ + { "ups.power.nominal", 0, 1.0, IETF_OID_CONF_OUT_VA, "", + 0, NULL }, + /* XUPS-MIB::xupsEnvAmbientTemp.0 */ + { "ups.temperature", 0, 1.0, "1.3.6.1.4.1.534.1.6.1.0", "", 0, NULL }, + /* FIXME: These 2 data needs RFC! */ + /* XUPS-MIB::xupsEnvAmbientLowerLimit.0 */ + { "ups.temperature.low", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.2.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvAmbientUpperLimit.0 */ + { "ups.temperature.high", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.3.0", "", 0, NULL }, + /* XUPS-MIB::xupsTestBatteryStatus */ + { "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.4.1.534.1.8.2.0", "", 0, &pw_batt_test_info[0] }, + /* UPS-MIB::upsAutoRestart */ + { "ups.start.auto", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.2.1.33.1.8.5.0", "", SU_FLAG_OK, &pw_yes_no_info[0] }, + /* XUPS-MIB::xupsBatteryAbmStatus.0 */ + { "battery.charger.status", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.4.1.534.1.2.5.0", "", SU_STATUS_BATT, &pw_abm_status_info[0] }, + + /* Battery page */ + { "battery.charge", 0, 1.0, PW_OID_BATT_CHARGE, "", + 0, NULL }, + { "battery.runtime", 0, 1.0, PW_OID_BATT_RUNTIME, "", + 0, NULL }, + { "battery.voltage", 0, 1.0, PW_OID_BATT_VOLTAGE, "", + 0, NULL }, + { "battery.current", 0, 0.1, PW_OID_BATT_CURRENT, "", + 0, NULL }, + { "battery.runtime.low", 0, 60.0, IETF_OID_CONF_RUNTIME_LOW, "", + 0, NULL }, + { "battery.date", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.1.2.6.0", NULL, SU_FLAG_OK, &su_convert_to_iso_date_info[FUNMAP_USDATE_TO_ISODATE] }, + + /* Output page */ + { "output.phases", 0, 1.0, PW_OID_OUT_LINES, "", 0, NULL }, + /* XUPS-MIB::xupsOutputFrequency.0 */ + { "output.frequency", 0, 0.1, "1.3.6.1.4.1.534.1.4.2.0", "", 0, NULL }, + /* XUPS-MIB::xupsConfigOutputFreq.0 */ + { "output.frequency.nominal", 0, 0.1, "1.3.6.1.4.1.534.1.10.4.0", "", 0, NULL }, + /* XUPS-MIB::xupsOutputVoltage.1 */ + { "output.voltage", 0, 1.0, "1.3.6.1.4.1.534.1.4.4.1.2.1", "", SU_OUTPUT_1, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* xupsOutputVoltage.1.0; Value (Integer): 230 */ + { "output.voltage", 0, 1.0, "1.3.6.1.4.1.534.1.4.4.1.2.1.0", "", SU_OUTPUT_1, NULL }, + /* XUPS-MIB::xupsConfigOutputVoltage.0 */ + { "output.voltage.nominal", 0, 1.0, "1.3.6.1.4.1.534.1.10.1.0", "", 0, NULL }, + /* XUPS-MIB::xupsConfigLowOutputVoltageLimit.0 */ + { "output.voltage.low", 0, 1.0, ".1.3.6.1.4.1.534.1.10.6.0", "", 0, NULL }, + /* XUPS-MIB::xupsConfigHighOutputVoltageLimit.0 */ + { "output.voltage.high", 0, 1.0, ".1.3.6.1.4.1.534.1.10.7.0", "", 0, NULL }, + { "output.current", 0, 1.0, PW_OID_OUT_CURRENT ".1", "", + SU_OUTPUT_1, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* xupsOutputCurrent.1.0; Value (Integer): 0 */ + { "output.current", 0, 1.0, "1.3.6.1.4.1.534.1.4.4.1.3.1.0", "", + SU_OUTPUT_1, NULL }, + { "output.realpower", 0, 1.0, PW_OID_OUT_POWER ".1", "", + SU_OUTPUT_1, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* Name/OID: xupsOutputWatts.1.0; Value (Integer): 1200 */ + { "output.realpower", 0, 1.0, "1.3.6.1.4.1.534.1.4.4.1.4.1.0", "", + 0, NULL }, + /* Duplicate of "ups.realpower.nominal" + * FIXME: map either ups or output, but not both (or have an auto-remap) */ + { "output.realpower.nominal", 0, 1.0, PW_OID_CONF_POWER, "", + 0, NULL }, + { "output.L1-N.voltage", 0, 1.0, PW_OID_OUT_VOLTAGE ".1", "", + SU_OUTPUT_3, NULL }, + { "output.L2-N.voltage", 0, 1.0, PW_OID_OUT_VOLTAGE ".2", "", + SU_OUTPUT_3, NULL }, + { "output.L3-N.voltage", 0, 1.0, PW_OID_OUT_VOLTAGE ".3", "", + SU_OUTPUT_3, NULL }, + { "output.L1.current", 0, 1.0, PW_OID_OUT_CURRENT ".1", "", + SU_OUTPUT_3, NULL }, + { "output.L2.current", 0, 1.0, PW_OID_OUT_CURRENT ".2", "", + SU_OUTPUT_3, NULL }, + { "output.L3.current", 0, 1.0, PW_OID_OUT_CURRENT ".3", "", + SU_OUTPUT_3, NULL }, + { "output.L1.realpower", 0, 1.0, PW_OID_OUT_POWER ".1", "", + SU_OUTPUT_3, NULL }, + { "output.L2.realpower", 0, 1.0, PW_OID_OUT_POWER ".2", "", + SU_OUTPUT_3, NULL }, + { "output.L3.realpower", 0, 1.0, PW_OID_OUT_POWER ".3", "", + SU_OUTPUT_3, NULL }, + /* FIXME: should better be output.Lx.load */ + { "output.L1.power.percent", 0, 1.0, IETF_OID_LOAD_LEVEL ".1", "", + SU_OUTPUT_3, NULL }, + { "output.L2.power.percent", 0, 1.0, IETF_OID_LOAD_LEVEL ".2", "", + SU_OUTPUT_3, NULL }, + { "output.L3.power.percent", 0, 1.0, IETF_OID_LOAD_LEVEL ".3", "", + SU_OUTPUT_3, NULL }, + { "output.voltage.nominal", 0, 1.0, PW_OID_CONF_OVOLTAGE, "", + 0, NULL }, + + /* Input page */ + { "input.phases", 0, 1.0, PW_OID_IN_LINES, "", + 0, NULL }, + { "input.frequency", 0, 0.1, PW_OID_IN_FREQUENCY, "", + 0, NULL }, + { "input.voltage", 0, 1.0, PW_OID_IN_VOLTAGE ".0", "", + SU_INPUT_1, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* xupsInputVoltage.1[.0]; Value (Integer): 245 */ + { "input.voltage", 0, 1.0, "1.3.6.1.4.1.534.1.3.4.1.2.1", "", + SU_INPUT_1, NULL }, + + /* XUPS-MIB::xupsConfigInputVoltage.0 */ + { "input.voltage.nominal", 0, 1.0, "1.3.6.1.4.1.534.1.10.2.0", "", 0, NULL }, + { "input.current", 0, 0.1, PW_OID_IN_CURRENT ".0", "", + SU_INPUT_1, NULL }, + { "input.L1-N.voltage", 0, 1.0, PW_OID_IN_VOLTAGE ".1", "", + SU_INPUT_3, NULL }, + { "input.L2-N.voltage", 0, 1.0, PW_OID_IN_VOLTAGE ".2", "", + SU_INPUT_3, NULL }, + { "input.L3-N.voltage", 0, 1.0, PW_OID_IN_VOLTAGE ".3", "", + SU_INPUT_3, NULL }, + { "input.L1.current", 0, 1.0, PW_OID_IN_CURRENT ".1", "", + SU_INPUT_3, NULL }, + { "input.L2.current", 0, 1.0, PW_OID_IN_CURRENT ".2", "", + SU_INPUT_3, NULL }, + { "input.L3.current", 0, 1.0, PW_OID_IN_CURRENT ".3", "", + SU_INPUT_3, NULL }, + { "input.L1.realpower", 0, 1.0, PW_OID_IN_POWER ".1", "", + SU_INPUT_3, NULL }, + { "input.L2.realpower", 0, 1.0, PW_OID_IN_POWER ".2", "", + SU_INPUT_3, NULL }, + { "input.L3.realpower", 0, 1.0, PW_OID_IN_POWER ".3", "", + SU_INPUT_3, NULL }, + { "input.quality", 0, 1.0, PW_OID_IN_LINE_BADS, "", + 0, NULL }, + + /* FIXME: this segfaults! do we assume the same number of bypass phases as input phases? + { "input.bypass.phases", 0, 1.0, PW_OID_BY_LINES, "", 0, NULL }, */ + { "input.bypass.frequency", 0, 0.1, PW_OID_BY_FREQUENCY, "", 0, NULL }, + { "input.bypass.voltage", 0, 1.0, PW_OID_BY_VOLTAGE ".0", "", + SU_INPUT_1, NULL }, + /* Duplicate of the above entry, but pointing at the first index */ + /* xupsBypassVoltage.1.0; Value (Integer): 244 */ + { "input.bypass.voltage", 0, 1.0, "1.3.6.1.4.1.534.1.5.3.1.2.1.0", "", + SU_INPUT_1, NULL }, + { "input.bypass.L1-N.voltage", 0, 1.0, PW_OID_BY_VOLTAGE ".1", "", + SU_INPUT_3, NULL }, + { "input.bypass.L2-N.voltage", 0, 1.0, PW_OID_BY_VOLTAGE ".2", "", + SU_INPUT_3, NULL }, + { "input.bypass.L3-N.voltage", 0, 1.0, PW_OID_BY_VOLTAGE ".3", "", + SU_INPUT_3, NULL }, + + /* Outlet page */ + /* Master outlet id always equal to 0 */ + { "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC , NULL }, + /* XUPS-MIB:: xupsSwitchable.0 */ + { "outlet.switchable", 0, 1, ".1.3.6.1.4.1.534.1.9.7.0", NULL, SU_FLAG_STATIC , &pw_yes_no_info[0] }, + /* XUPS-MIB::xupsNumReceptacles; Value (Integer): 2 */ + { "outlet.count", 0, 1, ".1.3.6.1.4.1.534.1.12.1.0", NULL, SU_FLAG_STATIC, NULL }, + /* XUPS-MIB::xupsRecepIndex.X; Value (Integer): X */ + { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.1.%i", NULL, SU_FLAG_STATIC | SU_OUTLET, NULL }, + /* This MIB does not provide outlets switchability info. So map to a nearby + OID, for data activation, and map all values to "yes" */ + { "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.1.%i", NULL, SU_FLAG_STATIC | SU_OUTLET, NULL }, + /* XUPS-MIB::xupsRecepStatus.X; Value (Integer): 1 */ + { "outlet.%i.status", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.2.%i", NULL, SU_OUTLET, &pw_outlet_status_info[0] }, + + /* Ambient collection */ + /* EMP001 (legacy) mapping */ + /* XUPS-MIB::xupsEnvRemoteTemp.0 */ + { "ambient.temperature", 0, 1.0, "1.3.6.1.4.1.534.1.6.5.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvRemoteTempLowerLimit.0 */ + { "ambient.temperature.low", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.9.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvRemoteTempUpperLimit.0 */ + { "ambient.temperature.high", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.10.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvRemoteHumidity.0 */ + { "ambient.humidity", 0, 1.0, "1.3.6.1.4.1.534.1.6.6.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvRemoteHumidityLowerLimit.0 */ + { "ambient.humidity.low", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.11.0", "", 0, NULL }, + /* XUPS-MIB::xupsEnvRemoteHumidityUpperLimit.0 */ + { "ambient.humidity.high", ST_FLAG_RW, 1.0, "1.3.6.1.4.1.534.1.6.12.0", "", 0, NULL }, + /* XUPS-MIB::xupsContactDescr.n */ + { "ambient.contacts.1.name", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.1.6.8.1.4.1", "", 0, NULL }, + { "ambient.contacts.2.name", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.1.6.8.1.4.2", "", 0, NULL }, + /* XUPS-MIB::xupsContactState.n */ + { "ambient.contacts.1.status", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.1.6.8.1.3.1", "", 0, &pw_ambient_drycontacts_info[0] }, + { "ambient.contacts.2.status", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.1.6.8.1.3.2", "", 0, &pw_ambient_drycontacts_info[0] }, + + /* EMP002 (EATON EMP MIB) mapping, including daisychain support */ + /* Warning: indexes start at '1' not '0'! */ + /* sensorCount.0 */ + { "ambient.count", ST_FLAG_RW, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.1.0", "", 0, NULL }, + /* CommunicationStatus.n */ + { "ambient.%i.present", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.8.1.1.4.1.1.%i", + NULL, SU_AMBIENT_TEMPLATE, &pw_emp002_ambient_presence_info[0] }, + /* sensorName.n: OctetString EMPDT1H1C2 @1 */ + { "ambient.%i.name", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.3.1.1.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorManufacturer.n */ + { "ambient.%i.mfr", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.2.1.6.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorModel.n */ + { "ambient.%i.model", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.2.1.7.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorSerialNumber.n */ + { "ambient.%i.serial", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.2.1.9.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorUuid.n */ + { "ambient.%i.id", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.2.1.2.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorAddress.n */ + { "ambient.%i.address", 0, 1, ".1.3.6.1.4.1.534.6.8.1.1.2.1.4.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* sensorFirmwareVersion.n */ + { "ambient.%i.firmware", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.1.2.1.10.%i", "", SU_AMBIENT_TEMPLATE, NULL }, + /* temperatureUnit.1 + * MUST be before the temperature data reading! */ + { "ambient.%i.temperature.unit", 0, 1.0, ".1.3.6.1.4.1.534.6.8.1.2.5.0", "", SU_AMBIENT_TEMPLATE, &pw_sensor_temperature_unit_info[0] }, + /* temperatureValue.n.1 */ + { "ambient.%i.temperature", 0, 0.1, ".1.3.6.1.4.1.534.6.8.1.2.3.1.3.%i.1", "", SU_AMBIENT_TEMPLATE, +#if WITH_SNMP_LKP_FUN + &pw_sensor_temperature_read_info[0] +#else + NULL +#endif + }, + { "ambient.%i.temperature.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.8.1.2.3.1.1.%i.1", + NULL, SU_AMBIENT_TEMPLATE, &pw_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.8.1.2.3.1.1.%i.1", + NULL, SU_AMBIENT_TEMPLATE, &pw_threshold_temperature_alarms_info[0] }, + /* FIXME: ambient.n.temperature.{minimum,maximum} */ + /* temperatureThresholdLowCritical.n.1 */ + { "ambient.%i.temperature.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.2.2.1.6.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* temperatureThresholdLowWarning.n.1 */ + { "ambient.%i.temperature.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.2.2.1.5.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* temperatureThresholdHighWarning.n.1 */ + { "ambient.%i.temperature.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.2.2.1.7.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* temperatureThresholdHighCritical.n.1 */ + { "ambient.%i.temperature.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.2.2.1.8.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* humidityValue.n.1 */ + { "ambient.%i.humidity", 0, 0.1, ".1.3.6.1.4.1.534.6.8.1.3.3.1.3.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + { "ambient.%i.humidity.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.8.1.3.3.1.1.%i.1", + NULL, SU_AMBIENT_TEMPLATE, &pw_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.8.1.3.3.1.1.%i.1", + NULL, SU_AMBIENT_TEMPLATE, &pw_threshold_humidity_alarms_info[0] }, + /* FIXME: consider ambient.n.humidity.{minimum,maximum} */ + /* humidityThresholdLowCritical.n.1 */ + { "ambient.%i.humidity.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.3.2.1.6.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* humidityThresholdLowWarning.n.1 */ + { "ambient.%i.humidity.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.3.2.1.5.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* humidityThresholdHighWarning.n.1 */ + { "ambient.%i.humidity.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.3.2.1.7.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* humidityThresholdHighCritical.n.1 */ + { "ambient.%i.humidity.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.8.1.3.2.1.8.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + /* digitalInputName.n.{1,2} */ + { "ambient.%i.contacts.1.name", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.4.2.1.1.%i.1", "", SU_AMBIENT_TEMPLATE, NULL }, + { "ambient.%i.contacts.2.name", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.4.2.1.1.%i.2", "", SU_AMBIENT_TEMPLATE, NULL }, + /* digitalInputPolarity.n */ + { "ambient.%i.contacts.1.config", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.8.1.4.2.1.3.%i.1", "", SU_AMBIENT_TEMPLATE, &pw_ambient_drycontacts_polarity_info[0] }, + { "ambient.%i.contacts.2.config", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.8.1.4.2.1.3.%i.2", "", SU_AMBIENT_TEMPLATE, &pw_ambient_drycontacts_polarity_info[0] }, + /* XUPS-MIB::xupsContactState.n */ + { "ambient.%i.contacts.1.status", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.4.3.1.3.%i.1", "", SU_AMBIENT_TEMPLATE, &pw_ambient_drycontacts_state_info[0] }, + { "ambient.%i.contacts.2.status", ST_FLAG_STRING, 1.0, ".1.3.6.1.4.1.534.6.8.1.4.3.1.3.%i.2", "", SU_AMBIENT_TEMPLATE, &pw_ambient_drycontacts_state_info[0] }, + + /* instant commands */ + { "test.battery.start.quick", 0, 1, PW_OID_BATTEST_START, "", + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* Shed load and restart when line power back on; cannot be canceled */ + { "shutdown.return", 0, DEFAULT_SHUTDOWNDELAY, PW_OID_CONT_LOAD_SHED_AND_RESTART, "", + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* Cancel output off, by writing 0 to xupsControlOutputOffDelay */ + { "shutdown.stop", 0, 0, PW_OID_CONT_OFFDELAY, "", + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* XUPS-MIB::xupsControlOutputOffDelay */ + /* load off after 1 sec, shortest possible delay; 0 cancels */ + { "load.off", 0, 1, PW_OID_CONT_OFFDELAY, "1", + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "load.off.delay", 0, 1, PW_OID_CONT_OFFDELAY, NULL, + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* XUPS-MIB::xupsControlOutputOnDelay */ + /* load on after 1 sec, shortest possible delay; 0 cancels */ + { "load.on", 0, 1, PW_OID_CONT_ONDELAY, "1", + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "load.on.delay", 0, 1, PW_OID_CONT_ONDELAY, NULL, + SU_TYPE_CMD | SU_FLAG_OK, NULL }, + + /* Delays handling: + * 0-n :Time in seconds until the command is issued + * -1:Cancel a pending Off/On command */ + /* XUPS-MIB::xupsRecepOffDelaySecs.n */ + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.3.%i", + "0", SU_TYPE_CMD | SU_OUTLET, NULL }, + /* XUPS-MIB::xupsRecepOnDelaySecs.n */ + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.4.%i", + "0", SU_TYPE_CMD | SU_OUTLET, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "outlet.%i.load.off.delay", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.3.%i", + NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + /* XUPS-MIB::xupsRecepOnDelaySecs.n */ + { "outlet.%i.load.on.delay", 0, 1, ".1.3.6.1.4.1.534.1.12.2.1.4.%i", + NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + + { "ups.alarms", 0, 1.0, PW_OID_ALARMS, "", + 0, NULL }, + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +} ; + +static alarms_info_t eaton_pxg_alarms[] = { + /* xupsLowBattery */ + { PW_OID_ALARM_LB, "LB", NULL }, + /* xupsOutputOverload */ + { ".1.3.6.1.4.1.534.1.7.7", "OVER", "Output overload!" }, + /* xupsInternalFailure */ + { ".1.3.6.1.4.1.534.1.7.8", NULL, "Internal failure!" }, + /* xupsBatteryDischarged */ + { ".1.3.6.1.4.1.534.1.7.9", NULL, "Battery discharged!" }, + /* xupsInverterFailure */ + { ".1.3.6.1.4.1.534.1.7.10", NULL, "Inverter failure!" }, + /* xupsOnBypass + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.11", "BYPASS", "On bypass!" }, + /* xupsBypassNotAvailable + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.12", NULL, "Bypass not available!" }, + /* xupsOutputOff + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.13", "OFF", "Output off!" }, + /* xupsInputFailure + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.14", NULL, "Input failure!" }, + /* xupsBuildingAlarm + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.15", NULL, "Building alarm!" }, + /* xupsShutdownImminent */ + { ".1.3.6.1.4.1.534.1.7.16", NULL, "Shutdown imminent!" }, + /* xupsOnInverter + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.17", NULL, "On inverter!" }, + /* xupsBreakerOpen + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.20", NULL, "Breaker open!" }, + /* xupsAlarmBatteryBad */ + { ".1.3.6.1.4.1.534.1.7.23", "RB", "Battery bad!" }, + /* xupsOutputOffAsRequested + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.24", "OFF", "Output off as requested!" }, + /* xupsDiagnosticTestFailed + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.25", NULL, "Diagnostic test failure!" }, + /* xupsCommunicationsLost */ + { ".1.3.6.1.4.1.534.1.7.26", NULL, "Communication with UPS lost!" }, + /* xupsUpsShutdownPending */ + { ".1.3.6.1.4.1.534.1.7.27", NULL, "Shutdown pending!" }, + /* xupsAmbientTempBad */ + { ".1.3.6.1.4.1.534.1.7.29", NULL, "Bad ambient temperature!" }, + /* xupsLossOfRedundancy */ + { ".1.3.6.1.4.1.534.1.7.30", NULL, "Redundancy lost!" }, + /* xupsAlarmTempBad */ + { ".1.3.6.1.4.1.534.1.7.31", NULL, "Bad temperature!" }, + /* xupsAlarmChargerFailed */ + { ".1.3.6.1.4.1.534.1.7.32", NULL, "Charger failure!" }, + /* xupsAlarmFanFailure */ + { ".1.3.6.1.4.1.534.1.7.33", NULL, "Fan failure!" }, + /* xupsAlarmFuseFailure */ + { ".1.3.6.1.4.1.534.1.7.34", NULL, "Fuse failure!" }, + /* xupsPowerSwitchBad */ + { ".1.3.6.1.4.1.534.1.7.35", NULL, "Powerswitch failure!" }, + /* xupsModuleFailure */ + { ".1.3.6.1.4.1.534.1.7.36", NULL, "Parallel or composite module failure!" }, + /* xupsOnAlternatePowerSource + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.37", NULL, "Using alternative power source!" }, + /* xupsAltPowerNotAvailable + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.38", NULL, "Alternative power source unavailable!" }, + /* xupsRemoteTempBad */ + { ".1.3.6.1.4.1.534.1.7.40", NULL, "Bad remote temperature!" }, + /* xupsRemoteHumidityBad */ + { ".1.3.6.1.4.1.534.1.7.41", NULL, "Bad remote humidity!" }, + /* xupsAlarmOutputBad */ + { ".1.3.6.1.4.1.534.1.7.42", NULL, "Bad output condition!" }, + /* xupsAlarmAwaitingPower + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? */ + { ".1.3.6.1.4.1.534.1.7.43", NULL, "Awaiting power!" }, + /* xupsOnMaintenanceBypass + * FIXME: informational (not an alarm), + * to RFC'ed for device.event? + * FIXME: NUT currently doesn't distinguish between Maintenance and + * Automatic Bypass (both published as "ups.alarm: BYPASS) + * Should we make the distinction? */ + { ".1.3.6.1.4.1.534.1.7.44", "BYPASS", "On maintenance bypass!" }, + + + /* end of structure. */ + { NULL, NULL, NULL } +} ; + + +mib2nut_info_t eaton_pxg_ups = { "eaton_pxg_ups", EATON_PXG_MIB_VERSION, NULL, PW_OID_MODEL_NAME, eaton_pxg_mib, EATON_PXGX_SYSOID , eaton_pxg_alarms }; diff --git a/drivers/powerware-mib.h b/drivers/eaton-ups-pxg-mib.h similarity index 64% rename from drivers/powerware-mib.h rename to drivers/eaton-ups-pxg-mib.h index 7189a247e0..78b0bc8d3f 100644 --- a/drivers/powerware-mib.h +++ b/drivers/eaton-ups-pxg-mib.h @@ -4,7 +4,6 @@ #include "main.h" #include "snmp-ups.h" -extern mib2nut_info_t powerware; -extern mib2nut_info_t pxgx_ups; +extern mib2nut_info_t eaton_pxg_ups; #endif /* POWERWARE_MIB_H */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index f2ac76dfa4..077ad6cb45 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -44,7 +44,6 @@ #include "apc-mib.h" #include "mge-mib.h" #include "netvision-mib.h" -#include "powerware-mib.h" #include "eaton-pdu-genesis2-mib.h" #include "eaton-pdu-marlin-mib.h" #include "eaton-pdu-pulizzi-mib.h" @@ -69,6 +68,8 @@ #include "hpe-pdu-mib.h" #include "hpe-pdu3-cis-mib.h" #include "eaton-pdu-nlogic-mib.h" +#include "eaton-ups-pwnm2-mib.h" +#include "eaton-ups-pxg-mib.h" /* Address API change */ #if ( ! NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol ) && ( ! defined usmAESPrivProtocol ) @@ -109,6 +110,8 @@ static mib2nut_info_t *mib2nut[] = { &eaton_ats30, /* This struct comes from : eaton-ats30-mib.c */ &eaton_marlin, /* This struct comes from : eaton-mib.c */ &eaton_pdu_nlogic, /* This struct comes from : eaton-pdu-nlogic-mib.c */ + &eaton_pxg_ups, /* This struct comes from : eaton-ups-pxg-mib.c */ + &eaton_pw_nm2, /* This struct comes from : eaton-ups-pwnm2-mib.c */ &emerson_avocent_pdu, /* This struct comes from : emerson-avocent-pdu-mib.c */ &aphel_revelation, /* This struct comes from : eaton-mib.c */ &aphel_genesisII, /* This struct comes from : eaton-mib.c */ @@ -119,8 +122,6 @@ static mib2nut_info_t *mib2nut[] = { &huawei, /* This struct comes from : huawei-mib.c */ &mge, /* This struct comes from : mge-mib.c */ &netvision, /* This struct comes from : netvision-mib.c */ - &powerware, /* This struct comes from : powerware-mib.c */ - &pxgx_ups, /* This struct comes from : powerware-mib.c */ &raritan, /* This struct comes from : raritan-pdu-mib.c */ &raritan_px2, /* This struct comes from : raritan-px2-mib.c */ &xppc, /* This struct comes from : xppc-mib.c */ @@ -172,7 +173,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.26" +#define DRIVER_VERSION "1.27" /* driver description structure */ upsdrv_info_t upsdrv_info = { From 6868034cca82ee52ace90aac1b2982c4d59fdd6f Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Thu, 24 Nov 2022 14:24:03 +0100 Subject: [PATCH 0086/1232] Spelling dictionnary completion Signed-off-by: Arnaud Quette --- docs/nut.dict | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/nut.dict b/docs/nut.dict index 0bbd8754d7..9a14b11220 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -2321,6 +2321,7 @@ nlb nlogic nn nnn +nm noAuthNoPriv nobody's nobt @@ -2516,6 +2517,7 @@ pwl pwmib pwro px +pxg pxgx py pycparser From 7150e17a2b07b5cb5d3c1fb6ece5894aee2129cf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 12:38:14 +0100 Subject: [PATCH 0087/1232] configure.ac: comment initial settings for RUN_AS_* and PIDPATH --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index 42df6a48d9..561a3682c7 100644 --- a/configure.ac +++ b/configure.ac @@ -118,11 +118,18 @@ case "${target_os}" in ;; esac +dnl Defaults for respective configure options below +dnl Note these defaults may change further below depending on OS and +dnl certain other configure options (e.g. "in-place replacement") RUN_AS_USER="nobody" RUN_AS_GROUP="nobody" AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GROUP}"`"], [RUN_AS_GROUP="nogroup"] ) + +dnl Historically this refers to *system location* for PID files, and +dnl then NUT init-scripts, systemd-tmpfiles integration or some such +dnl create and chown a "nut" subdirectory there for the daemons to use. PIDPATH="/var/run" dnl Define directory where LIBOBJS replacement functions are From 0e0cbf573190c154624b07a2280f60ba25ceb34d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 12:39:51 +0100 Subject: [PATCH 0088/1232] configure.ac: move final processing of --with-user and --with-group to end of script --- configure.ac | 94 +++++++++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/configure.ac b/configure.ac index 561a3682c7..b8642d363c 100644 --- a/configure.ac +++ b/configure.ac @@ -2189,51 +2189,6 @@ AC_ARG_WITH(port, AC_DEFINE_UNQUOTED(PORT, ${PORT}, [Port for network communications]) AC_MSG_RESULT(${PORT}) -AC_MSG_CHECKING(user to run as) -AC_ARG_WITH(user, - AS_HELP_STRING([--with-user=username], [user for programs started as root (${RUN_AS_USER})]), -[ - case "${withval}" in - yes|no) - AC_MSG_ERROR(invalid option --with(out)-user - see docs/configure.txt) - ;; - *) - RUN_AS_USER="${withval}" - nut_user_given=yes - ;; - esac -], [ - nut_user_given=no -]) -AC_DEFINE_UNQUOTED(RUN_AS_USER, "${RUN_AS_USER}", [User to switch to if started as root]) -AC_MSG_RESULT(${RUN_AS_USER}) - -AC_MSG_CHECKING(group membership of user to run as) -AC_ARG_WITH(group, - AS_HELP_STRING([--with-group=groupname], [group membership of user for programs started as root (${RUN_AS_GROUP})]), -[ - case "${withval}" in - yes|no) - AC_MSG_ERROR(invalid option --with(out)-group - see docs/configure.txt) - ;; - *) - RUN_AS_GROUP="${withval}" - nut_group_given=yes - ;; - esac -], [ - nut_group_given=no -]) -AC_DEFINE_UNQUOTED(RUN_AS_GROUP, "${RUN_AS_GROUP}", [Group membership of user to switch to if started as root]) -AC_MSG_RESULT(${RUN_AS_GROUP}) - -dnl check that --with-user is given if --with-group is given. -if test "${nut_user_given}" = "yes" -a "${nut_group_given}" = "no"; then - AC_MSG_ERROR([If you specify --with-user, you also must specify --with-group]) -elif test "${nut_user_given}" = "no" -a "${nut_group_given}" = "yes"; then - AC_MSG_ERROR([If you specify --with-group, you also must specify --with-user]) -fi - AC_MSG_CHECKING(facility for syslog) AC_ARG_WITH(logfacility, AS_HELP_STRING([--with-logfacility=FACILITY], [facility for log messages (LOG_DAEMON)]), @@ -3060,6 +3015,55 @@ fi dnl ---------------------------------------------------------------------- +dnl Check the user and group to run as last, so we can use the paths configured +dnl above as data sources for default values if building an in-place replacement +AC_MSG_CHECKING(user to run as) +AC_ARG_WITH(user, + AS_HELP_STRING([--with-user=username], [user for programs started as root (${RUN_AS_USER})]), +[ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-user - see docs/configure.txt) + ;; + *) + RUN_AS_USER="${withval}" + nut_user_given=yes + ;; + esac +], [ + nut_user_given=no +]) +AC_DEFINE_UNQUOTED(RUN_AS_USER, "${RUN_AS_USER}", [User to switch to if started as root]) +AC_MSG_RESULT(${RUN_AS_USER}) + +AC_MSG_CHECKING(group membership of user to run as) +AC_ARG_WITH(group, + AS_HELP_STRING([--with-group=groupname], [group membership of user for programs started as root (${RUN_AS_GROUP})]), +[ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-group - see docs/configure.txt) + ;; + *) + RUN_AS_GROUP="${withval}" + nut_group_given=yes + ;; + esac +], [ + nut_group_given=no +]) +AC_DEFINE_UNQUOTED(RUN_AS_GROUP, "${RUN_AS_GROUP}", [Group membership of user to switch to if started as root]) +AC_MSG_RESULT(${RUN_AS_GROUP}) + +dnl check that --with-user is given if --with-group is given. +if test "${nut_user_given}" = "yes" -a "${nut_group_given}" = "no"; then + AC_MSG_ERROR([If you specify --with-user, you also must specify --with-group]) +elif test "${nut_user_given}" = "no" -a "${nut_group_given}" = "yes"; then + AC_MSG_ERROR([If you specify --with-group, you also must specify --with-user]) +fi + +dnl ---------------------------------------------------------------------- + dnl Current date now=`TZ=UTC date +%Y-%m-%d` From 40cca03650b3e30f762c6dbccf00f7f0c89cecd7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 12:56:43 +0100 Subject: [PATCH 0089/1232] configure.ac: introduce --enable-inplace-runtime and impact default RUN_AS_USER and RUN_AS_GROUP by that --- configure.ac | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b8642d363c..2060566288 100644 --- a/configure.ac +++ b/configure.ac @@ -118,15 +118,35 @@ case "${target_os}" in ;; esac +dnl Note: this deals with run-time settings so that the newly built +dnl programs can be "just executed" to use same configuration files +dnl and filesystem object permissions as an older deployment of NUT +dnl on this system; this specifically does not deal with trying to +dnl use same prefix and other paths to fully replace an older setup +dnl (a different option might be crafted to do that, but really the +dnl arcane distro-dependent packaging recipes are a better way here). +dnl This feature is intended for users who want to see if a custom +dnl build of NUT supports their hardware or other use-cases better. +NUT_ARG_ENABLE([inplace-runtime], + [Request configure option defaults for runtime user/group/confpath based on currently installed NUT (to extent these can be detected)], + [no]) + dnl Defaults for respective configure options below dnl Note these defaults may change further below depending on OS and dnl certain other configure options (e.g. "in-place replacement") RUN_AS_USER="nobody" RUN_AS_GROUP="nobody" AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GROUP}"`"], - [RUN_AS_GROUP="nogroup"] + [RUN_AS_GROUP="nogroup"] ) +AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ + AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], + [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) + AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], + [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])]) +]) + dnl Historically this refers to *system location* for PID files, and dnl then NUT init-scripts, systemd-tmpfiles integration or some such dnl create and chown a "nut" subdirectory there for the daemons to use. From 1f5a00efd4c17fd220a05f3964eca1f034d5ebbd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 12:58:25 +0100 Subject: [PATCH 0090/1232] configure.ac: change AS_HELP_STRINGs for hotplugdir, udevdir and devddir to report current defaults (not arbitrary suggestions) --- configure.ac | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 2060566288..e9a5e6cdfc 100644 --- a/configure.ac +++ b/configure.ac @@ -2747,7 +2747,7 @@ fi AC_MSG_CHECKING(whether to install hotplug rules) AC_ARG_WITH(hotplug-dir, - AS_HELP_STRING([--with-hotplug-dir=PATH], [where to install hotplug rules (/etc/hotplug)]), + AS_HELP_STRING([--with-hotplug-dir=PATH], [where to install hotplug rules (${hotplugdir}); typically /etc/hotplug]), [ case "${withval}" in yes) @@ -2775,10 +2775,10 @@ AM_CONDITIONAL(WITH_HOTPLUG, test -n "${hotplugdir}") AC_MSG_CHECKING(whether to install udev rules) AC_ARG_WITH(udev-dir, - AS_HELP_STRING([--with-udev-dir=PATH], [where to install udev rules (/lib/udev or /etc/udev)]), + AS_HELP_STRING([--with-udev-dir=PATH], [where to install udev rules (${udevdir}; typically /lib/udev or /etc/udev)]), [ case "${withval}" in - yes) + yes) dnl Typically /lib/udev or /etc/udev if test -z "${udevdir}"; then AC_MSG_RESULT(no) AC_MSG_ERROR([udev directory requested but not found]) @@ -2813,10 +2813,10 @@ dnl FreeBSD devd support: AC_MSG_CHECKING(whether to install FreeBSD devd.conf file) AC_ARG_WITH(devd-dir, - AS_HELP_STRING([--with-devd-dir=PATH], [where to install devd.conf file (/usr/local/etc/devd or /etc/devd)]), + AS_HELP_STRING([--with-devd-dir=PATH], [where to install devd.conf file (${devddir}; typically /usr/local/etc/devd or /etc/devd)]), [ case "${withval}" in - yes) + yes) dnl Typically /usr/local/etc/devd or /etc/devd if test -z "${devddir}"; then AC_MSG_RESULT(no) AC_MSG_ERROR([devd directory requested but not found]) From 24742543be65ca810b4b9ce66db97766845295f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:11:44 +0100 Subject: [PATCH 0091/1232] configure.ac: impact default sysconfdir by --enable-inplace-runtime --- configure.ac | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configure.ac b/configure.ac index e9a5e6cdfc..ddf4d04756 100644 --- a/configure.ac +++ b/configure.ac @@ -141,6 +141,25 @@ AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GR ) AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ + dnl If there was no custom --sysconfdir=/etc/myNUT passed, try to default + dnl TODO: Smarter ways welcome (e.g. reliably look at configure CLI opts) + AS_IF([test x"${prefix}/etc" = x"${sysconfdir}"], [ + dnl TODO: Any more reasonable defaults? Pile them on here :) + for D in \ + /etc/nut /etc/ups \ + /usr/etc/nut /usr/etc/ups \ + /usr/local/etc/nut /usr/local/etc/ups \ + /usr/local/nut/etc /usr/local/ups/etc \ + ; do + if test -e "$D/ups.conf" || test -e "$D/upsmon.conf" \ + || ( test -e "$D/upsd.conf" && test -e "$D/upsd.users" ) \ + ; then + sysconfdir="$D" + break + fi + done + ]) + AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], From 558476decafa36e9964374c9a09bb20ecf0be880 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:25:11 +0100 Subject: [PATCH 0092/1232] docs/configure.txt: update for `--enable-inplace-runtime` [#1714] --- docs/configure.txt | 24 +++++++++++++++++++++++- docs/nut.dict | 3 ++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/configure.txt b/docs/configure.txt index c681f74791..5b0416c38e 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -7,6 +7,26 @@ There are a few options reviewed below that can be given to `configure` script to tweak your compilations. See also `./configure --help` for a current and complete listing for the current version of the codebase. +In-place replacement defaults +----------------------------- + +A common situation for NUT builds is to verify whether current version +of the codebase (e.g. recent and not-yet-packaged release, or a Git branch) +solves some issues of an existing deployment. Such tests are simplified +if the new build of NUT plays by the same systems integration rules as +the already deployed (e.g. package-delivered) version, specifically about +filesystem access permissions and configuration file locations. + + --enable-inplace-runtime + +Tries to detect and pre-set `configure` defaults for run-time settings +(which you can still override if needed, but no longer *must* specify +explicitly to be on same page as the existing setup): + +* --sysconfdir +* --with-user +* --with-group + Driver selection ---------------- @@ -311,6 +331,8 @@ Daemon user accounts --with-user= --with-group= +See also `--enable-inplace-runtime`. + Programs started as `root` will `setuid()` to `` for somewhat safer operation. You can override this with `-u ` in several programs, including `upsdrvctl` (and all drivers by extension), `upsd`, @@ -371,7 +393,7 @@ default, it is the same as ``. Changes the location where NUT's configuration files are stored. By default this path is `/etc`. Setting this to `/etc/nut` or -`/etc/ups` might be useful. +`/etc/ups` might be useful. See also `--enable-inplace-runtime`. The `NUT_CONFPATH` environment variable overrides this at run time. diff --git a/docs/nut.dict b/docs/nut.dict index 9a14b11220..e61a0605cd 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3058 utf-8 +personal_ws-1.1 en 3059 utf-8 AAS ABI ACFAIL @@ -2017,6 +2017,7 @@ initscripts initups inline innotech +inplace installcheck installurl instcmd From 7e5e398709c52eee4c6ce3afe2069a3bcaf534f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:28:24 +0100 Subject: [PATCH 0093/1232] NEWS: update for `configure --enable-inplace-runtime` [#1714] --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index b19273a997..fe91901808 100644 --- a/NEWS +++ b/NEWS @@ -60,6 +60,11 @@ https://github.com/networkupstools/nut/milestone/8 * Fixed building of NUT man pages when just a few drivers are selected by `configure` script for custom builds [#1467] + - New `configure --enable-inplace-runtime` option should set default values + for `--sysconfdir`, `--with-user` and `--with-group` options to match an + existing NUT deployment -- for users who are trying if a custom build + of recent codebase solves their practical issues [#1714] + - We lacked log information about changes of chroot jail (uncommon) and of UID/GID (everywhere), which makes troubleshooting harder (e.g. lack of access to config files or USB device nodes). Now we have it [#1694] From 9e6c641a1bd446ae3adc44a6275808bfd057bb20 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:32:48 +0100 Subject: [PATCH 0094/1232] configure.ac: report if checking for better sysconfdir/user/group and how it went --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index ddf4d04756..46836039ef 100644 --- a/configure.ac +++ b/configure.ac @@ -144,6 +144,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ dnl If there was no custom --sysconfdir=/etc/myNUT passed, try to default dnl TODO: Smarter ways welcome (e.g. reliably look at configure CLI opts) AS_IF([test x"${prefix}/etc" = x"${sysconfdir}"], [ + AC_MSG_CHECKING([for in-place replacement default sysconfdir (better than '${sysconfdir}')]) dnl TODO: Any more reasonable defaults? Pile them on here :) for D in \ /etc/nut /etc/ups \ @@ -158,12 +159,18 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ break fi done + AC_MSG_RESULT([${sysconfdir}]) ]) + AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) + AC_MSG_RESULT([${RUN_AS_GROUP}]) + + AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])]) + AC_MSG_RESULT([${RUN_AS_USER}]) ]) dnl Historically this refers to *system location* for PID files, and From 868f18733a3cd477369e340fa19643954aa0868d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:34:18 +0100 Subject: [PATCH 0095/1232] configure.ac: move checking for better default user/group based on current system circumstances down, to just before we use them --- configure.ac | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 46836039ef..95a2649f1b 100644 --- a/configure.ac +++ b/configure.ac @@ -161,16 +161,6 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ done AC_MSG_RESULT([${sysconfdir}]) ]) - - AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) - AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], - [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) - AC_MSG_RESULT([${RUN_AS_GROUP}]) - - AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) - AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], - [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])]) - AC_MSG_RESULT([${RUN_AS_USER}]) ]) dnl Historically this refers to *system location* for PID files, and @@ -3060,9 +3050,21 @@ if test -n "${target_cpu}" -a -n "${target_os}" ; then fi dnl ---------------------------------------------------------------------- - dnl Check the user and group to run as last, so we can use the paths configured dnl above as data sources for default values if building an in-place replacement + +AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ + AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) + AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], + [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) + AC_MSG_RESULT([${RUN_AS_GROUP}]) + + AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) + AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], + [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])]) + AC_MSG_RESULT([${RUN_AS_USER}]) +]) + AC_MSG_CHECKING(user to run as) AC_ARG_WITH(user, AS_HELP_STRING([--with-user=username], [user for programs started as root (${RUN_AS_USER})]), From d8d0b035f9be9a8b1ebc15bc17f39f7c8679edd4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:44:05 +0100 Subject: [PATCH 0096/1232] ci_build.sh: add support for INPLACE_RUNTIME=true --- ci_build.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index de842388c4..17db88f9d9 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -970,6 +970,10 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp CONFIG_OPTS+=("--with-devd-dir=${BUILD_PREFIX}/etc/devd") CONFIG_OPTS+=("--with-hotplug-dir=${BUILD_PREFIX}/etc/hotplug") + if [ x"${INPLACE_RUNTIME-}" = xtrue ]; then + CONFIG_OPTS+=("--enable-inplace-runtime") + fi + # TODO: Consider `--enable-maintainer-mode` to add recipes that # would quickly regenerate Makefile(.in) if you edit Makefile.am # TODO: Resolve port-collision reliably (for multi-executor agents) @@ -1759,7 +1763,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp bindings) pushd "./bindings/${BINDING}" && ./ci_build.sh ;; -"") +""|inplace) echo "ERROR: No BUILD_TYPE was specified, doing a minimal default ritual without any required options" >&2 if [ -n "${BUILD_WARNOPT}${BUILD_WARNFATAL}" ]; then echo "WARNING: BUILD_WARNOPT and BUILD_WARNFATAL settings are ignored in this mode" >&2 @@ -1793,13 +1797,21 @@ bindings) # Below we aim for really fast iterations of C/C++ development so # enable whatever is auto-detectable (except docs), and highlight # any warnings if we can. - ${CONFIGURE_SCRIPT} --enable-Wcolor \ + CONFIG_OPTS=(--enable-Wcolor \ --enable-keep_nut_report_feature \ --with-all=auto --with-cgi=auto --with-serial=auto \ --with-dev=auto --with-doc=skip \ --with-nut_monitor=auto --with-pynut=auto \ --disable-force-nut-version-header \ - --enable-check-NIT --enable-maintainer-mode + --enable-check-NIT --enable-maintainer-mode) + + # Not default for parameter-less build, to prevent "make check-NIT" + # from somehow interfering with the running daemons. + if [ x"${INPLACE_RUNTIME-}" = xtrue ] || [ x"${BUILD_TYPE-}" = xinplace ] ; then + CONFIG_OPTS+=("--enable-inplace-runtime") + fi + + ${CONFIGURE_SCRIPT} "${CONFIG_OPTS[@]}" # NOTE: Currently parallel builds are expected to succeed (as far # as recipes are concerned), and the builds without a BUILD_TYPE From 1367217b11bac3b6036e66acbda9c0a9af5c0df5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 13:49:43 +0100 Subject: [PATCH 0097/1232] NEWS: add `./ci_build.sh inplace` operation shortcut [#1714] --- NEWS | 3 ++- ci_build.sh | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index fe91901808..4028c01ada 100644 --- a/NEWS +++ b/NEWS @@ -63,7 +63,8 @@ https://github.com/networkupstools/nut/milestone/8 - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an existing NUT deployment -- for users who are trying if a custom build - of recent codebase solves their practical issues [#1714] + of recent codebase solves their practical issues. For "quick tests", a + shortcut operation `./ci_build.sh inplace` was added [#1714] - We lacked log information about changes of chroot jail (uncommon) and of UID/GID (everywhere), which makes troubleshooting harder (e.g. lack diff --git a/ci_build.sh b/ci_build.sh index 17db88f9d9..961aa6b70c 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -683,6 +683,11 @@ optional_dist_clean_check() { return 0 } +if [ "$1" = inplace ] && [ -z "$BUILD_TYPE" ] ; then + shift + BUILD_TYPE="inplace" +fi + if [ "$1" = spellcheck ] && [ -z "$BUILD_TYPE" ] ; then # Note: this is a little hack to reduce typing # and scrolling in (docs) developer iterations. From 46b8020fd3977080d9ead9dfd0712f5c33a43caf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 14:00:21 +0100 Subject: [PATCH 0098/1232] m4/nut_report_feature.m4: introduce NUT_REPORT_SETTING() ...and comment arguments for NUT_REPORT_FEATURE() --- m4/nut_report_feature.m4 | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 5b9fd59936..c292d9c1eb 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -5,7 +5,10 @@ dnl nut_with_usb and WITH_USB (both macros, and dnl AM_CONDITIONAL) AC_DEFUN([NUT_REPORT], -[ if test -z "${nut_report_feature_flag}"; then +[ + dnl $1 = description (summary) + dnl $2 = value + if test -z "${nut_report_feature_flag}"; then nut_report_feature_flag="1" dnl By (legacy) default we remove this report file dnl For CI we want to publish its artifact @@ -22,6 +25,11 @@ AC_DEFUN([NUT_REPORT], AC_DEFUN([NUT_REPORT_FEATURE], [ + dnl $1 = summary/config.log description + dnl $2 = test flag ("yes" or not) + dnl $3 = value + dnl $4 = autoconf varname + dnl $5 = longer description (autoconf comment) AC_MSG_CHECKING([whether to $1]) AC_MSG_RESULT([$2 $3]) NUT_REPORT([$1], [$2 $3]) @@ -32,6 +40,20 @@ AC_DEFUN([NUT_REPORT_FEATURE], fi ]) +AC_DEFUN([NUT_REPORT_SETTING], +[ + dnl $1 = summary/config.log description + dnl $2 = autoconf varname + dnl $3 = value + dnl $4 = description (summary and autoconf) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT([$1], [$3]) + + # Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) +]) + AC_DEFUN([NUT_REPORT_COMPILERS], [ (echo "" From 857c057e7b819bc6f74fa889c0d6f0b67546df62 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Fri, 25 Nov 2022 14:47:59 +0100 Subject: [PATCH 0099/1232] snmp-ups: fix "Warning: excessive poll failures" Fix that long standing issue, which was tied to non-existent OIDs, not well handled in some part of the driver Closes: #743 Signed-off-by: Arnaud Quette --- NEWS | 3 +++ drivers/snmp-ups.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b19273a997..c8b8ef992a 100644 --- a/NEWS +++ b/NEWS @@ -117,6 +117,9 @@ https://github.com/networkupstools/nut/milestone/8 * Better manage the slight nuances (especially in ups.status) between Eaton UPSs, and rename mibs from 'pw' to 'eaton_pw_nm2', and from 'pxgx_ups' to 'eaton_pxg_ups' + * Fixed the long standing "Warning: excessive poll failures" issue, that + was tied to non-existent OIDs, not well handled in some part of the driver + - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 077ad6cb45..33376adb34 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -173,7 +173,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.27" +#define DRIVER_VERSION "1.28" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -1132,6 +1132,7 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) break; } + if (!((status == STAT_SUCCESS) && (response->errstat == SNMP_ERR_NOERROR))) { if (mibname == NULL) { /* We are probing for proper mib - ignore errors */ @@ -1140,7 +1141,18 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) return NULL; } + if (response->errstat == SNMP_ERR_NOSUCHNAME) { + upsdebugx(4, "%s: OID does not exist, skipping", __func__); + snmp_free_pdu(response); + nut_snmp_free(ret_array); + return NULL; + } + + upsdebugx(3, "status = %i, response->errstat = %li", status, response->errstat); + + /* Error throttling otherwise */ numerr++; + upsdebugx(4, "%s: numerr++ (total=%i)", __func__, numerr); if ((numerr == SU_ERR_LIMIT) || ((numerr % SU_ERR_RATE) == 0)) { upslogx(LOG_WARNING, "[%s] Warning: excessive poll " @@ -2810,6 +2822,7 @@ bool_t get_and_process_data(int mode, snmp_info_t *su_info_p) } else { if (mode == SU_WALKMODE_INIT) { /* handle unsupported vars */ + upsdebugx(4, "%s: Disabling var '%s'", __func__, su_info_p->info_type); su_info_p->flags &= ~SU_FLAG_OK; } else { if (!(su_info_p->flags & SU_FLAG_STALE)) { From 8655920de2eaa681219d5a2391496b75d2bc817d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 14:42:40 +0100 Subject: [PATCH 0100/1232] configure.ac: change AS_HELP_STRINGs and some other comments/messages for STATEPATH and PIDPATH to clarify --- configure.ac | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 95a2649f1b..0c3197e3e9 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ dnl Historically this refers to *system location* for PID files, and dnl then NUT init-scripts, systemd-tmpfiles integration or some such dnl create and chown a "nut" subdirectory there for the daemons to use. +dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below. PIDPATH="/var/run" dnl Define directory where LIBOBJS replacement functions are @@ -2095,7 +2096,7 @@ dnl ---------------------------------------------------------------------- AC_MSG_CHECKING(state path) AC_ARG_WITH(statepath, - AS_HELP_STRING([--with-statepath=PATH], [path for ups state files (/var/state/ups)]), + AS_HELP_STRING([--with-statepath=PATH], [path for ups state files (${STATEPATH}, typically /var/state/ups)]), [ case "${withval}" in yes|no) @@ -2118,7 +2119,7 @@ dnl AC_MSG_CHECKING(alt pid path) AC_ARG_WITH(altpidpath, - AS_HELP_STRING([--with-altpidpath=PATH], [path for driver/upsd .pid files ()]), + AS_HELP_STRING([--with-altpidpath=PATH], [path for NUT driver/upsd .pid files not running as root ()]), [ case "${withval}" in yes|no) @@ -2193,7 +2194,7 @@ AC_MSG_RESULT(${htmldir}) AC_MSG_CHECKING(pidpath) AC_ARG_WITH(pidpath, - AS_HELP_STRING([--with-pidpath=PATH], [path for .pid files (/var/run)]), + AS_HELP_STRING([--with-pidpath=PATH], [system base path for .pid files (${PIDPATH}, typically /var/run and ./nut will be created there)]), [ case "${withval}" in yes|no) @@ -2204,7 +2205,7 @@ AC_ARG_WITH(pidpath, ;; esac ], []) -AC_DEFINE_UNQUOTED(PIDPATH, "${PIDPATH}", [Path where the pid files should go]) +AC_DEFINE_UNQUOTED(PIDPATH, "${PIDPATH}", [System path where the pid files should go]) AC_MSG_RESULT(${PIDPATH}) AC_MSG_CHECKING(network port number) From b3e91c86d82967e4b42b8dafbb812d58ae714134 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 14:56:39 +0100 Subject: [PATCH 0101/1232] configure.ac: NUT_REPORT_SETTING() for RUN_AS_USER and RUN_AS_GROUP --- configure.ac | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 0c3197e3e9..d8d974e215 100644 --- a/configure.ac +++ b/configure.ac @@ -3077,13 +3077,15 @@ AC_ARG_WITH(user, *) RUN_AS_USER="${withval}" nut_user_given=yes + AC_MSG_RESULT([specified]) ;; esac ], [ nut_user_given=no + AC_MSG_RESULT([default]) ]) -AC_DEFINE_UNQUOTED(RUN_AS_USER, "${RUN_AS_USER}", [User to switch to if started as root]) -AC_MSG_RESULT(${RUN_AS_USER}) +NUT_REPORT_SETTING([User to run as], + RUN_AS_USER, "${RUN_AS_USER}", [User to switch to if started as root]) AC_MSG_CHECKING(group membership of user to run as) AC_ARG_WITH(group, @@ -3096,13 +3098,15 @@ AC_ARG_WITH(group, *) RUN_AS_GROUP="${withval}" nut_group_given=yes + AC_MSG_RESULT([specified]) ;; esac ], [ nut_group_given=no + AC_MSG_RESULT([default]) ]) -AC_DEFINE_UNQUOTED(RUN_AS_GROUP, "${RUN_AS_GROUP}", [Group membership of user to switch to if started as root]) -AC_MSG_RESULT(${RUN_AS_GROUP}) +NUT_REPORT_SETTING([Group of user to run as], + RUN_AS_GROUP, "${RUN_AS_GROUP}", [Group membership of user to switch to if started as root]) dnl check that --with-user is given if --with-group is given. if test "${nut_user_given}" = "yes" -a "${nut_group_given}" = "no"; then From cb68569a77e96876cb9e0baa1761e944e2990284 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 14:57:43 +0100 Subject: [PATCH 0102/1232] configure.ac: fix generation of systemd/nut-common.tmpfiles Should have no "nut" subdir for STATEPATH and ALTPIDPATH Follow-up for #1030, #1037, #1117 May be related to #1712 --- configure.ac | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index d8d974e215..7121c70e87 100644 --- a/configure.ac +++ b/configure.ac @@ -3512,8 +3512,8 @@ AS_IF([test -n "$systemdtmpfilesdir"], [mkdir -p "${TOP_BUILDDIR}"/scripts/systemd cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF # State file (e.g. upsd to driver) and pidfile location for NUT: -d @STATEPATH@/nut 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - -X @STATEPATH@/nut +d @STATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - +X @STATEPATH@ EOF AS_IF([test "$STATEPATH" != "$PIDPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF @@ -3522,13 +3522,14 @@ X @PIDPATH@/nut EOF]) AS_IF([test -n "$ALTPIDPATH" && test "$STATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTPIDPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF -d @ALTPIDPATH@/nut 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - -X @ALTPIDPATH@/nut +d @ALTPIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - +X @ALTPIDPATH@ EOF]) + dnl Generally added to support some forks AS_IF([test -n "$ALTSTATEPATH" && test "$STATEPATH" != "$ALTSTATEPATH" && test "$ALTSTATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTSTATEPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF -d @ALTSTATEPATH@/nut 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - -X @ALTSTATEPATH@/nut +d @ALTSTATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - +X @ALTSTATEPATH@ EOF]) ]) AC_MSG_RESULT([done]) From 48a083eeb65948d1440e2bab05ac1f6cdf623d5d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 15:08:16 +0100 Subject: [PATCH 0103/1232] configure.ac: use NUT_REPORT_SETTING() for various path tunables --- configure.ac | 59 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/configure.ac b/configure.ac index 7121c70e87..360831ee8f 100644 --- a/configure.ac +++ b/configure.ac @@ -2104,11 +2104,12 @@ AC_ARG_WITH(statepath, ;; *) STATEPATH="${withval}" + AC_MSG_RESULT([specified]) ;; esac -], []) -AC_DEFINE_UNQUOTED(STATEPATH, "${STATEPATH}", [Path for UPS driver state files]) -AC_MSG_RESULT(${STATEPATH}) +], [AC_MSG_RESULT([default])]) +NUT_REPORT_SETTING([State file path], + STATEPATH, "${STATEPATH}", [Path for UPS driver state files]) dnl --------------------------------------------------------------------- dnl The 'alt pid path' is used by the drivers (via main.c) and upsd, since @@ -2127,13 +2128,15 @@ AC_ARG_WITH(altpidpath, ;; *) ALTPIDPATH="${withval}" + AC_MSG_RESULT([specified]) ;; esac ], [ ALTPIDPATH="${STATEPATH}" + AC_MSG_RESULT([default]) ]) -AC_DEFINE_UNQUOTED(ALTPIDPATH, "${ALTPIDPATH}", [Path for pid files of drivers and upsd (usually STATEPATH)]) -AC_MSG_RESULT(${ALTPIDPATH}) +NUT_REPORT_SETTING([Unprivileged PID file path], + ALTPIDPATH, "${ALTPIDPATH}", [Path for pid files of processes not running as root, such as drivers and upsd (usually STATEPATH)]) AC_MSG_CHECKING(driver path) AC_ARG_WITH(drvpath, @@ -2145,14 +2148,15 @@ AC_ARG_WITH(drvpath, ;; *) driverexecdir="${withval}" + AC_MSG_RESULT([specified]) ;; esac -], []) +], [AC_MSG_RESULT([default])]) conftemp="${driverexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -AC_DEFINE_UNQUOTED(DRVPATH, "${conftemp}", [Default path for UPS drivers]) -AC_MSG_RESULT(${driverexecdir}) +NUT_REPORT_SETTING([Driver program path], + DRVPATH, "${conftemp}", [Default path for UPS drivers]) AC_MSG_CHECKING(cgi path) AC_ARG_WITH(cgipath, @@ -2164,14 +2168,15 @@ AC_ARG_WITH(cgipath, ;; *) cgiexecdir="${withval}" + AC_MSG_RESULT([specified]) ;; esac -], []) +], [AC_MSG_RESULT([default])]) conftemp="${cgiexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -AC_DEFINE_UNQUOTED(CGIPATH, "${conftemp}", [Default path for CGI programs]) -AC_MSG_RESULT(${cgiexecdir}) +NUT_REPORT_SETTING([CGI program path], + CGIPATH, "${conftemp}", [Default path for CGI programs]) AC_MSG_CHECKING(html path) AC_ARG_WITH(htmlpath, @@ -2183,14 +2188,15 @@ AC_ARG_WITH(htmlpath, ;; *) htmldir="${withval}" + AC_MSG_RESULT([specified]) ;; esac -], []) +], [AC_MSG_RESULT([default])]) conftemp="${htmldir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -AC_DEFINE_UNQUOTED(HTMLPATH, "${conftemp}", [Default path for HTML files]) -AC_MSG_RESULT(${htmldir}) +NUT_REPORT_SETTING([HTML file path], + HTMLPATH, "${conftemp}", [Default path for HTML files (CGI templates)]) AC_MSG_CHECKING(pidpath) AC_ARG_WITH(pidpath, @@ -2202,11 +2208,12 @@ AC_ARG_WITH(pidpath, ;; *) PIDPATH="${withval}" + AC_MSG_RESULT([specified]) ;; esac -], []) -AC_DEFINE_UNQUOTED(PIDPATH, "${PIDPATH}", [System path where the pid files should go]) -AC_MSG_RESULT(${PIDPATH}) +], [AC_MSG_RESULT([default])]) +NUT_REPORT_SETTING([System PID file path], + PIDPATH, "${PIDPATH}", [System default path where the pid files should go]) AC_MSG_CHECKING(network port number) AC_ARG_WITH(port, @@ -2961,42 +2968,48 @@ conftemp="${sysconfdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" CONFPATH=${conftemp} -AC_DEFINE_UNQUOTED(CONFPATH, "${conftemp}", [Default path for configuration files]) +NUT_REPORT_SETTING([Config file path], + CONFPATH, "${conftemp}", [Default path for configuration files]) dnl same for datadir conftemp="${datadir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" NUT_DATADIR=${conftemp} -AC_DEFINE_UNQUOTED(NUT_DATADIR, "${conftemp}", [Default path for data files]) +NUT_REPORT_SETTING([Data file path], + NUT_DATADIR, "${conftemp}", [Default path for data files]) dnl same for bindir conftemp="${bindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" BINDIR=${conftemp} -AC_DEFINE_UNQUOTED(BINDIR, "${conftemp}", [Default path for user executables]) +NUT_REPORT_SETTING([Tool program path], + BINDIR, "${conftemp}", [Default path for user executables]) dnl same for sbindir conftemp="${sbindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" SBINDIR=${conftemp} -AC_DEFINE_UNQUOTED(SBINDIR, "${conftemp}", [Default path for system executables]) +NUT_REPORT_SETTING([System program path], + SBINDIR, "${conftemp}", [Default path for system executables]) dnl same for libdir conftemp="${libdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" LIBDIR=${conftemp} -AC_DEFINE_UNQUOTED(LIBDIR, "${conftemp}", [Default path for system libraries]) +NUT_REPORT_SETTING([System library path], + LIBDIR, "${conftemp}", [Default path for system libraries]) dnl same for libexecdir conftemp="${libexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" LIBEXECDIR=${conftemp} -AC_DEFINE_UNQUOTED(LIBEXECDIR, "${conftemp}", [Default path for system exec-libraries]) +NUT_REPORT_SETTING([System exec-library path], + LIBEXECDIR, "${conftemp}", [Default path for system exec-libraries]) dnl checks related to --with-snmp enabled on command-line From 8889b19754e6610a374270c402369b2061bdc761 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 15:11:13 +0100 Subject: [PATCH 0104/1232] Makefile.am: install-win-bundle-thirdparty: fix indentations --- Makefile.am | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile.am b/Makefile.am index 027572ce04..edf0fe4874 100644 --- a/Makefile.am +++ b/Makefile.am @@ -371,18 +371,18 @@ install-win-bundle-thirdparty: @if test -z "$$ARCH" ; then \ if test -n "$(target)" ; then \ ARCH='$(target)' \ - ; else \ - if test -n "$(target_triplet)" ; then ARCH='$(target_triplet)' ; fi ; \ - fi ; \ - fi ; \ - if test -n "$$ARCH" ; then export ARCH ; fi ; \ - DESTDIR='$(DESTDIR)' ; export DESTDIR ; \ + ; else \ + if test -n "$(target_triplet)" ; then ARCH='$(target_triplet)' ; fi ; \ + fi ; \ + fi ; \ + if test -n "$$ARCH" ; then export ARCH ; fi ; \ + DESTDIR='$(DESTDIR)' ; export DESTDIR ; \ ( cd '$(DESTDIR)' || exit ; \ DESTDIR="" '$(abs_top_srcdir)/scripts/Windows/dllldd.sh' dllldddir . \ | while read D ; do \ echo " DLL->bin $$D" 2>&1 ; \ cp -pf "$$D" './$(bindir)/' ; \ - done ; \ + done ; \ ) || exit ; \ ( if test x"$(bindir)" = x"$(sbindir)" ; then exit 0 ; fi ; \ cd '$(DESTDIR)/$(sbindir)' || exit ; \ @@ -390,7 +390,7 @@ install-win-bundle-thirdparty: | while read D ; do \ echo " DLL->sbin $$D" 2>&1 ; \ ln -f '$(DESTDIR)/$(bindir)'/"`basename "$$D"`" ./ ; \ - done ; \ + done ; \ ) || exit ; \ ( if test x"$(driverexecdir)" = x"$(bindir)" ; then exit 0 ; fi ; \ if test x"$(driverexecdir)" = x"$(sbindir)" ; then exit 0 ; fi ; \ @@ -399,7 +399,7 @@ install-win-bundle-thirdparty: | while read D ; do \ echo " DLL->drv $$D" 2>&1 ; \ ln -f '$(DESTDIR)/$(bindir)'/"`basename "$$D"`" ./ ; \ - done ; \ + done ; \ ) || exit ; \ ( if test -z "$(cgiexecdir)" -o ! -d "$(DESTDIR)/$(cgiexecdir)" ; then exit 0 ; fi ; \ if test x"$(cgiexecdir)" = x"$(bindir)" ; then exit 0 ; fi ; \ @@ -410,7 +410,7 @@ install-win-bundle-thirdparty: | while read D ; do \ echo " DLL->cgi $$D" 2>&1 ; \ ln -f '$(DESTDIR)/$(bindir)'/"`basename "$$D"`" ./ ; \ - done ; \ + done ; \ ) || exit @echo "CHECKING if any executable files were installed to locations other than those covered by this recipe, so might not have needed DLLs bundled near them" >&2 ; \ relbindir="`echo './$(bindir)/' | sed 's,//*,/,g'`" ; \ From 4fa03c5c99291f7b586af2faad0c916b74e7927c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 15:14:46 +0100 Subject: [PATCH 0105/1232] ci_build.sh: in case of success for default build, remind the chosen config.nut_report_feature.log settings --- ci_build.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 961aa6b70c..726e9de0f3 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1833,6 +1833,10 @@ bindings) echo "(or some other valid DESTDIR) to co-bundle dependency FOSS DLL files there." >&2 ;; esac + + if [ -s config.nut_report_feature.log ]; then + cat config.nut_report_feature.log + fi ;; # These mingw modes below are currently experimental and not too integrated From b78150ea6bb13c3757de179da2c970f2c399c650 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 15:17:30 +0100 Subject: [PATCH 0106/1232] m4/nut_report_feature.m4: change markup of usage() comments to avoid m4 surprises --- m4/nut_report_feature.m4 | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index c292d9c1eb..2a76b2863c 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -6,8 +6,8 @@ dnl AM_CONDITIONAL) AC_DEFUN([NUT_REPORT], [ - dnl $1 = description (summary) - dnl $2 = value + dnl arg#1 = description (summary) + dnl arg#2 = value if test -z "${nut_report_feature_flag}"; then nut_report_feature_flag="1" dnl By (legacy) default we remove this report file @@ -25,11 +25,11 @@ AC_DEFUN([NUT_REPORT], AC_DEFUN([NUT_REPORT_FEATURE], [ - dnl $1 = summary/config.log description - dnl $2 = test flag ("yes" or not) - dnl $3 = value - dnl $4 = autoconf varname - dnl $5 = longer description (autoconf comment) + dnl arg#1 = summary/config.log description + dnl arg#2 = test flag ("yes" or not) + dnl arg#3 = value + dnl arg#4 = autoconf varname + dnl arg#5 = longer description (autoconf comment) AC_MSG_CHECKING([whether to $1]) AC_MSG_RESULT([$2 $3]) NUT_REPORT([$1], [$2 $3]) @@ -42,15 +42,15 @@ AC_DEFUN([NUT_REPORT_FEATURE], AC_DEFUN([NUT_REPORT_SETTING], [ - dnl $1 = summary/config.log description - dnl $2 = autoconf varname - dnl $3 = value - dnl $4 = description (summary and autoconf) + dnl arg#1 = summary/config.log description + dnl arg#2 = autoconf varname + dnl arg#3 = value + dnl arg#4 = description (summary and autoconf) AC_MSG_CHECKING([setting for $1]) AC_MSG_RESULT([$3]) NUT_REPORT([$1], [$3]) - # Note: unlike features, settings do not imply an AutoMake toggle + dnl Note: unlike features, settings do not imply an AutoMake toggle AC_DEFINE_UNQUOTED($2, $3, $4) ]) From 951c50b3275884acb8b8b71635032035f20dc1cf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 16:02:55 +0100 Subject: [PATCH 0107/1232] m4/nut_report_feature.m4: refactor to hold and append different summary chapters in different files [#1708 follow-up] --- .gitignore | 2 +- Makefile.am | 2 +- m4/nut_report_feature.m4 | 52 +++++++++++++++++++++++++++------------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 50504e1cac..9862e66834 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ Makefile.in /config.h /config.cache /configure -/config.nut_report_feature.log +/config.nut_report_feature.log* /conf??????/ /dir.??????/ /dir?.???????/ diff --git a/Makefile.am b/Makefile.am index edf0fe4874..75caf8a7d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -213,7 +213,7 @@ endif !HAVE_CPPCHECK MAINTAINERCLEANFILES += ChangeLog # CI builds can leave a log of selected features: -MAINTAINERCLEANFILES += config.nut_report_feature.log +MAINTAINERCLEANFILES += config.nut_report_feature.log* # Older boundary of the ChangeLog commits range # It can be a tag ('v2.2.0'), a commit hash, a date, ... diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 2a76b2863c..ae7863b49a 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -4,23 +4,32 @@ dnl for example, "usb" (--with-usb) will give dnl nut_with_usb and WITH_USB (both macros, and dnl AM_CONDITIONAL) +AC_DEFUN([NUT_REPORT_FILE], +[ + dnl arg#1 = description (summary) + dnl arg#2 = value + dnl arg#3 = file tag (e.g. number) + dnl arg#4 = file title (e.g. "NUT Configuration summary:") + if test -z "${nut_report_feature_flag$3}"; then + nut_report_feature_flag$3="1" + ac_clean_files="${ac_clean_files} config.nut_report_feature.log.$3" + if [ "$3" = 1 ]; then + echo "$4" + else + echo "" + echo "$4" + fi > "config.nut_report_feature.log.$3" + echo "$4" | sed 's/./=/g' >> "config.nut_report_feature.log.$3" + echo "" >> "config.nut_report_feature.log.$3" + fi + echo "* $1: $2" >> "config.nut_report_feature.log.$3" +]) + AC_DEFUN([NUT_REPORT], [ dnl arg#1 = description (summary) dnl arg#2 = value - if test -z "${nut_report_feature_flag}"; then - nut_report_feature_flag="1" - dnl By (legacy) default we remove this report file - dnl For CI we want to publish its artifact - dnl Manageable by "--enable-keep_nut_report_feature" - AS_IF([test x"${nut_enable_keep_nut_report_feature-}" = xyes], - [AC_MSG_NOTICE([Will keep config.nut_report_feature.log])], - [ac_clean_files="${ac_clean_files} config.nut_report_feature.log"]) - echo "NUT Configuration summary:" > config.nut_report_feature.log - echo "==========================" >> config.nut_report_feature.log - echo "" >> config.nut_report_feature.log - fi - echo "* $1: $2" >> config.nut_report_feature.log + NUT_REPORT_FILE($1, $2, 1, "NUT Configuration summary:") ]) AC_DEFUN([NUT_REPORT_FEATURE], @@ -66,11 +75,22 @@ AC_DEFUN([NUT_REPORT_COMPILERS], printf '* CXXFLAGS\t: %s\n' "$CXXFLAGS" printf '* CPP \t: %s\n' "$CPP" printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" - ) >> config.nut_report_feature.log + ) > config.nut_report_feature.log.9 ]) AC_DEFUN([NUT_PRINT_FEATURE_REPORT], [ - echo "" - cat config.nut_report_feature.log + dnl By (legacy) default we remove this report file + dnl For CI we want to publish its artifact + dnl Manageable by "--enable-keep_nut_report_feature" + echo "" + AS_IF([test x"${nut_enable_keep_nut_report_feature-}" = xyes], + [AC_MSG_NOTICE([Will keep config.nut_report_feature.log]) + cat config.nut_report_feature.log.* > config.nut_report_feature.log + cat config.nut_report_feature.log + ], + [dnl Remove if exists from old builds + ac_clean_files="${ac_clean_files} config.nut_report_feature.log" + cat config.nut_report_feature.log.* + ]) ]) From 5891d9cb79104c93881ffd326f224a9c4a73f66a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 16:03:48 +0100 Subject: [PATCH 0108/1232] m4/nut_report_feature.m4: add separate chapter for NUT_REPORT_PATH() and NUT_REPORT_SETTING_PATH() to populate it --- m4/nut_report_feature.m4 | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index ae7863b49a..d56eff821f 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -32,6 +32,13 @@ AC_DEFUN([NUT_REPORT], NUT_REPORT_FILE($1, $2, 1, "NUT Configuration summary:") ]) +AC_DEFUN([NUT_REPORT_PATH], +[ + dnl arg#1 = description (summary) + dnl arg#2 = value + NUT_REPORT_FILE($1, $2, 2, "NUT Paths:") +]) + AC_DEFUN([NUT_REPORT_FEATURE], [ dnl arg#1 = summary/config.log description @@ -63,6 +70,20 @@ AC_DEFUN([NUT_REPORT_SETTING], AC_DEFINE_UNQUOTED($2, $3, $4) ]) +AC_DEFUN([NUT_REPORT_SETTING_PATH], +[ + dnl arg#1 = summary/config.log description + dnl arg#2 = autoconf varname + dnl arg#3 = value + dnl arg#4 = description (summary and autoconf) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT_PATH([$1], [$3]) + + dnl Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) +]) + AC_DEFUN([NUT_REPORT_COMPILERS], [ (echo "" From 80efa9421d7c86dc87f6306b93fde19d5053a32e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 16:04:31 +0100 Subject: [PATCH 0109/1232] configure.ac: refactor to use NUT_REPORT_SETTING_PATH() to summarize separately from other toggles [#1708 follow-up] --- configure.ac | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 360831ee8f..858438b10c 100644 --- a/configure.ac +++ b/configure.ac @@ -2108,7 +2108,7 @@ AC_ARG_WITH(statepath, ;; esac ], [AC_MSG_RESULT([default])]) -NUT_REPORT_SETTING([State file path], +NUT_REPORT_SETTING_PATH([State file path], STATEPATH, "${STATEPATH}", [Path for UPS driver state files]) dnl --------------------------------------------------------------------- @@ -2135,7 +2135,7 @@ AC_ARG_WITH(altpidpath, ALTPIDPATH="${STATEPATH}" AC_MSG_RESULT([default]) ]) -NUT_REPORT_SETTING([Unprivileged PID file path], +NUT_REPORT_SETTING_PATH([Unprivileged PID file path], ALTPIDPATH, "${ALTPIDPATH}", [Path for pid files of processes not running as root, such as drivers and upsd (usually STATEPATH)]) AC_MSG_CHECKING(driver path) @@ -2155,7 +2155,7 @@ AC_ARG_WITH(drvpath, conftemp="${driverexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -NUT_REPORT_SETTING([Driver program path], +NUT_REPORT_SETTING_PATH([Driver program path], DRVPATH, "${conftemp}", [Default path for UPS drivers]) AC_MSG_CHECKING(cgi path) @@ -2175,7 +2175,7 @@ AC_ARG_WITH(cgipath, conftemp="${cgiexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -NUT_REPORT_SETTING([CGI program path], +NUT_REPORT_SETTING_PATH([CGI program path], CGIPATH, "${conftemp}", [Default path for CGI programs]) AC_MSG_CHECKING(html path) @@ -2195,7 +2195,7 @@ AC_ARG_WITH(htmlpath, conftemp="${htmldir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -NUT_REPORT_SETTING([HTML file path], +NUT_REPORT_SETTING_PATH([HTML file path], HTMLPATH, "${conftemp}", [Default path for HTML files (CGI templates)]) AC_MSG_CHECKING(pidpath) @@ -2212,7 +2212,7 @@ AC_ARG_WITH(pidpath, ;; esac ], [AC_MSG_RESULT([default])]) -NUT_REPORT_SETTING([System PID file path], +NUT_REPORT_SETTING_PATH([System PID file path], PIDPATH, "${PIDPATH}", [System default path where the pid files should go]) AC_MSG_CHECKING(network port number) @@ -2968,7 +2968,7 @@ conftemp="${sysconfdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" CONFPATH=${conftemp} -NUT_REPORT_SETTING([Config file path], +NUT_REPORT_SETTING_PATH([Config file path], CONFPATH, "${conftemp}", [Default path for configuration files]) dnl same for datadir @@ -2976,7 +2976,7 @@ conftemp="${datadir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" NUT_DATADIR=${conftemp} -NUT_REPORT_SETTING([Data file path], +NUT_REPORT_SETTING_PATH([Data file path], NUT_DATADIR, "${conftemp}", [Default path for data files]) dnl same for bindir @@ -2984,7 +2984,7 @@ conftemp="${bindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" BINDIR=${conftemp} -NUT_REPORT_SETTING([Tool program path], +NUT_REPORT_SETTING_PATH([Tool program path], BINDIR, "${conftemp}", [Default path for user executables]) dnl same for sbindir @@ -2992,7 +2992,7 @@ conftemp="${sbindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" SBINDIR=${conftemp} -NUT_REPORT_SETTING([System program path], +NUT_REPORT_SETTING_PATH([System program path], SBINDIR, "${conftemp}", [Default path for system executables]) dnl same for libdir @@ -3000,7 +3000,7 @@ conftemp="${libdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" LIBDIR=${conftemp} -NUT_REPORT_SETTING([System library path], +NUT_REPORT_SETTING_PATH([System library path], LIBDIR, "${conftemp}", [Default path for system libraries]) dnl same for libexecdir @@ -3008,7 +3008,7 @@ conftemp="${libexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" LIBEXECDIR=${conftemp} -NUT_REPORT_SETTING([System exec-library path], +NUT_REPORT_SETTING_PATH([System exec-library path], LIBEXECDIR, "${conftemp}", [Default path for system exec-libraries]) From 831b431926a9d676187016afa5c93dbdb430c47e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 18:33:37 +0100 Subject: [PATCH 0110/1232] configure.ac: clarify that PIDPATH *is* for NUT directly (privileged daemons) [#123, #1712] --- configure.ac | 53 ++++++++++++++++++++++++---------------------- docs/configure.txt | 5 +++-- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/configure.ac b/configure.ac index 858438b10c..dca705d8be 100644 --- a/configure.ac +++ b/configure.ac @@ -163,10 +163,10 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ ]) ]) -dnl Historically this refers to *system location* for PID files, and -dnl then NUT init-scripts, systemd-tmpfiles integration or some such -dnl create and chown a "nut" subdirectory there for the daemons to use. -dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below. +dnl Historically this refers to *system location* for PID files, +dnl and more specifically that for `upsmon` (running as `root`). +dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below +dnl for the unprivileged daemons (`upsd`, drivers). PIDPATH="/var/run" dnl Define directory where LIBOBJS replacement functions are @@ -2138,6 +2138,23 @@ AC_ARG_WITH(altpidpath, NUT_REPORT_SETTING_PATH([Unprivileged PID file path], ALTPIDPATH, "${ALTPIDPATH}", [Path for pid files of processes not running as root, such as drivers and upsd (usually STATEPATH)]) +AC_MSG_CHECKING(pidpath) +AC_ARG_WITH(pidpath, + AS_HELP_STRING([--with-pidpath=PATH], [Path for root-owned .pid files (${PIDPATH}, typically /var/run)]), +[ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-pidpath - see docs/configure.txt) + ;; + *) + PIDPATH="${withval}" + AC_MSG_RESULT([specified]) + ;; + esac +], [AC_MSG_RESULT([default])]) +NUT_REPORT_SETTING_PATH([Privileged PID file path], + PIDPATH, "${PIDPATH}", [Path for pid files of processes running as root, such as upsmon]) + AC_MSG_CHECKING(driver path) AC_ARG_WITH(drvpath, AS_HELP_STRING([--with-drvpath=PATH], [where to install UPS drivers (EPREFIX/bin)]), @@ -2198,23 +2215,6 @@ eval conftemp=\"${conftemp}\" NUT_REPORT_SETTING_PATH([HTML file path], HTMLPATH, "${conftemp}", [Default path for HTML files (CGI templates)]) -AC_MSG_CHECKING(pidpath) -AC_ARG_WITH(pidpath, - AS_HELP_STRING([--with-pidpath=PATH], [system base path for .pid files (${PIDPATH}, typically /var/run and ./nut will be created there)]), -[ - case "${withval}" in - yes|no) - AC_MSG_ERROR(invalid option --with(out)-pidpath - see docs/configure.txt) - ;; - *) - PIDPATH="${withval}" - AC_MSG_RESULT([specified]) - ;; - esac -], [AC_MSG_RESULT([default])]) -NUT_REPORT_SETTING_PATH([System PID file path], - PIDPATH, "${PIDPATH}", [System default path where the pid files should go]) - AC_MSG_CHECKING(network port number) AC_ARG_WITH(port, AS_HELP_STRING([--with-port=PORT], [port for network communications (3493)]), @@ -3529,10 +3529,13 @@ d @STATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @STATEPATH@ EOF AS_IF([test "$STATEPATH" != "$PIDPATH"], - [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF -d @PIDPATH@/nut 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - -X @PIDPATH@/nut -EOF]) + [AS_CASE(["${PIDPATH}"], + [*/run], [], dnl Do not intrude into system paths; TODO: add more if appropriate for some Linux distro + [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF +d @PIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - +X @PIDPATH@ +EOF +])]) AS_IF([test -n "$ALTPIDPATH" && test "$STATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTPIDPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF d @ALTPIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - diff --git a/docs/configure.txt b/docs/configure.txt index 5b0416c38e..2d90384d5d 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -544,8 +544,9 @@ Directories used by NUT at run-time --with-pidpath=PATH -Changes the directory where pid files are stored. By default this is -`/var/run`. Certain programs like `upsmon` will leave files here. +Changes the directory where NUT pid files are stored for processes running +as `root`. By default this is `/var/run`. Certain programs like `upsmon` +will leave files here. --with-altpidpath=PATH From 48a7a3e7cda7f1d1af6b70ecd33c3250414813f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 19:00:09 +0100 Subject: [PATCH 0111/1232] m4/nut_report_feature.m4: refactor NUT_REPORT_FILE() for second-level headings and less file-openings --- m4/nut_report_feature.m4 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index d56eff821f..615a7aed91 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -15,12 +15,14 @@ AC_DEFUN([NUT_REPORT_FILE], ac_clean_files="${ac_clean_files} config.nut_report_feature.log.$3" if [ "$3" = 1 ]; then echo "$4" + echo "$4" | sed 's/./=/g' + echo "" else echo "" echo "$4" + echo "$4" | sed 's/./-/g' + echo "" fi > "config.nut_report_feature.log.$3" - echo "$4" | sed 's/./=/g' >> "config.nut_report_feature.log.$3" - echo "" >> "config.nut_report_feature.log.$3" fi echo "* $1: $2" >> "config.nut_report_feature.log.$3" ]) From 6523b5799906155fa2e4d32d2deb0fa44ab2f471 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 19:27:25 +0100 Subject: [PATCH 0112/1232] m4/nut_report_feature.m4: fix comments --- m4/nut_report_feature.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 615a7aed91..e7272b7b4f 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -63,7 +63,7 @@ AC_DEFUN([NUT_REPORT_SETTING], dnl arg#1 = summary/config.log description dnl arg#2 = autoconf varname dnl arg#3 = value - dnl arg#4 = description (summary and autoconf) + dnl arg#4 = longer description (autoconf comment) AC_MSG_CHECKING([setting for $1]) AC_MSG_RESULT([$3]) NUT_REPORT([$1], [$3]) @@ -77,7 +77,7 @@ AC_DEFUN([NUT_REPORT_SETTING_PATH], dnl arg#1 = summary/config.log description dnl arg#2 = autoconf varname dnl arg#3 = value - dnl arg#4 = description (summary and autoconf) + dnl arg#4 = longer description (autoconf comment) AC_MSG_CHECKING([setting for $1]) AC_MSG_RESULT([$3]) NUT_REPORT_PATH([$1], [$3]) From a78bcbf6bcbbf6e1e93a4e4dbd2583d6c34380c4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 19:27:53 +0100 Subject: [PATCH 0113/1232] m4/nut_report_feature.m4: add NUT_REPORT_TARGET [#1708] --- m4/nut_report_feature.m4 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index e7272b7b4f..8853581fd0 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -86,6 +86,19 @@ AC_DEFUN([NUT_REPORT_SETTING_PATH], AC_DEFINE_UNQUOTED($2, $3, $4) ]) +AC_DEFUN([NUT_REPORT_TARGET], +[ + dnl arg#1 = autoconf varname + dnl arg#2 = value + dnl arg#3 = summary/config.log/autoconf description + AC_MSG_CHECKING([$3]) + AC_MSG_RESULT([$2]) + NUT_REPORT_FILE([$3], [$2], 8, "NUT Build/Target system info:") + + dnl Note: unlike features, target info does not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($1, $2, $3) +]) + AC_DEFUN([NUT_REPORT_COMPILERS], [ (echo "" From 32f0c10ad3e9295565545e39f31adf1196b9558e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 19:29:32 +0100 Subject: [PATCH 0114/1232] configure.ac: use NUT_REPORT_TARGET [#1708] --- configure.ac | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index dca705d8be..f4f7cc22fb 100644 --- a/configure.ac +++ b/configure.ac @@ -3032,35 +3032,35 @@ NUT_REPORT_FEATURE([build SNMP drivers with statically linked lib(net)snmp], [${ if test -n "${host_alias}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_HOST_ALIAS, "${host_alias}", [host env spec we run on]) + NUT_REPORT_TARGET(AUTOTOOLS_HOST_ALIAS, "${host_alias}", [host env spec we run on]) else if test -n "${host}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_HOST_ALIAS, "${host}", [host env spec we run on]) + NUT_REPORT_TARGET(AUTOTOOLS_HOST_ALIAS, "${host}", [host env spec we run on]) fi fi if test -n "${build_alias}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_BUILD_ALIAS, "${build_alias}", [host env spec we built on]) + NUT_REPORT_TARGET(AUTOTOOLS_BUILD_ALIAS, "${build_alias}", [host env spec we built on]) else if test -n "${build}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_BUILD_ALIAS, "${build}", [host env spec we built on]) + NUT_REPORT_TARGET(AUTOTOOLS_BUILD_ALIAS, "${build}", [host env spec we built on]) fi fi if test -n "${target_alias}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_TARGET_ALIAS, "${target_alias}", [host env spec we built for]) + NUT_REPORT_TARGET(AUTOTOOLS_TARGET_ALIAS, "${target_alias}", [host env spec we built for]) else if test -n "${target}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_TARGET_ALIAS, "${target}", [host env spec we built for]) + NUT_REPORT_TARGET(AUTOTOOLS_TARGET_ALIAS, "${target}", [host env spec we built for]) fi fi if test -n "${host_cpu}" -a -n "${host_os}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_HOST_SHORT_ALIAS, "${host_cpu}-${host_os}", [host OS short spec we run on]) + NUT_REPORT_TARGET(AUTOTOOLS_HOST_SHORT_ALIAS, "${host_cpu}-${host_os}", [host OS short spec we run on]) fi if test -n "${build_cpu}" -a -n "${build_os}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_BUILD_SHORT_ALIAS, "${build_cpu}-${build_os}", [host OS short spec we built on]) + NUT_REPORT_TARGET(AUTOTOOLS_BUILD_SHORT_ALIAS, "${build_cpu}-${build_os}", [host OS short spec we built on]) fi if test -n "${target_cpu}" -a -n "${target_os}" ; then - AC_DEFINE_UNQUOTED(AUTOTOOLS_TARGET_SHORT_ALIAS, "${target_cpu}-${target_os}", [host OS short spec we built for]) + NUT_REPORT_TARGET(AUTOTOOLS_TARGET_SHORT_ALIAS, "${target_cpu}-${target_os}", [host OS short spec we built for]) fi dnl ---------------------------------------------------------------------- From 7105d4465ed4988aff526871d2070ea51e789fe4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 19:33:50 +0100 Subject: [PATCH 0115/1232] m4/nut_report_feature.m4: align reports with tabulation --- m4/nut_report_feature.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 8853581fd0..ce854c6bba 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -24,7 +24,7 @@ AC_DEFUN([NUT_REPORT_FILE], echo "" fi > "config.nut_report_feature.log.$3" fi - echo "* $1: $2" >> "config.nut_report_feature.log.$3" + printf "* $1:\t$2\n" >> "config.nut_report_feature.log.$3" ]) AC_DEFUN([NUT_REPORT], From 26003429c04077718bf2b152b2bb6d56f586d590 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 20:30:15 +0100 Subject: [PATCH 0116/1232] m4/nut_report_feature.m4: fix detection of chapter "1" and other nuances --- m4/nut_report_feature.m4 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index ce854c6bba..d57b40cae7 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -13,7 +13,7 @@ AC_DEFUN([NUT_REPORT_FILE], if test -z "${nut_report_feature_flag$3}"; then nut_report_feature_flag$3="1" ac_clean_files="${ac_clean_files} config.nut_report_feature.log.$3" - if [ "$3" = 1 ]; then + if test x1 = x$3 ; then echo "$4" echo "$4" | sed 's/./=/g' echo "" @@ -31,14 +31,14 @@ AC_DEFUN([NUT_REPORT], [ dnl arg#1 = description (summary) dnl arg#2 = value - NUT_REPORT_FILE($1, $2, 1, "NUT Configuration summary:") + NUT_REPORT_FILE([$1], [$2], [1], "NUT Configuration summary:") ]) AC_DEFUN([NUT_REPORT_PATH], [ dnl arg#1 = description (summary) dnl arg#2 = value - NUT_REPORT_FILE($1, $2, 2, "NUT Paths:") + NUT_REPORT_FILE([$1], [$2], [2], "NUT Paths:") ]) AC_DEFUN([NUT_REPORT_FEATURE], @@ -93,7 +93,7 @@ AC_DEFUN([NUT_REPORT_TARGET], dnl arg#3 = summary/config.log/autoconf description AC_MSG_CHECKING([$3]) AC_MSG_RESULT([$2]) - NUT_REPORT_FILE([$3], [$2], 8, "NUT Build/Target system info:") + NUT_REPORT_FILE([$3], [$2], [8], "NUT Build/Target system info:") dnl Note: unlike features, target info does not imply an AutoMake toggle AC_DEFINE_UNQUOTED($1, $2, $3) @@ -112,6 +112,7 @@ AC_DEFUN([NUT_REPORT_COMPILERS], printf '* CPP \t: %s\n' "$CPP" printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" ) > config.nut_report_feature.log.9 + ac_clean_files="${ac_clean_files} config.nut_report_feature.log.9" ]) AC_DEFUN([NUT_PRINT_FEATURE_REPORT], From c56b1e5514468cefec2dcf179518095f8f8568c9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:07:25 +0100 Subject: [PATCH 0117/1232] configure.ac: report "$prefix" --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index f4f7cc22fb..cc098c5032 100644 --- a/configure.ac +++ b/configure.ac @@ -2093,6 +2093,8 @@ AM_CONDITIONAL([HAVE_WINDOWS], [test "${nut_have_mingw_resgen}" = "yes"]) dnl ---------------------------------------------------------------------- +NUT_REPORT_SETTING_PATH([Default installation prefix path], + PREFIX, "${prefix}", [Default installation prefix path]) AC_MSG_CHECKING(state path) AC_ARG_WITH(statepath, From fa66e9d2da8688ad9d25e228a93efc53548fbe6f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:07:39 +0100 Subject: [PATCH 0118/1232] configure.ac: AC_SUBST(ALTPIDPATH) --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index cc098c5032..311629bfe3 100644 --- a/configure.ac +++ b/configure.ac @@ -3174,6 +3174,8 @@ AC_SUBST(NETLIBS) AC_SUBST(SERLIBS) AC_SUBST(PIDPATH) AC_SUBST(STATEPATH) +AC_SUBST(ALTPIDPATH) +dnl #Not in main codebase yet# AC_SUBST(ALTSTATEPATH) AC_SUBST(CONFPATH) AC_SUBST(BINDIR) AC_SUBST(LIBDIR) From 19372be8012cf3b0e45853519829999cf3c96065 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:20:56 +0100 Subject: [PATCH 0119/1232] Reference init-script and packaging templates: eradicate "@PIDPATH@/nut" ambiguity in favor of "@ALTPIDPATH@" (and explicitly ensure "@PIDPATH@" where applicable) [#1712] --- scripts/Aix/nut.init.in | 2 +- scripts/HP-UX/postinstall.in | 17 +++++++++++------ scripts/Solaris/nut-server.xml.in | 2 +- scripts/Solaris/postinstall.in | 15 ++++++++++----- scripts/Solaris/postremove.in | 6 +++++- scripts/Solaris/svc-nut-monitor.in | 3 ++- scripts/Solaris/svc-nut-server.in | 3 ++- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/scripts/Aix/nut.init.in b/scripts/Aix/nut.init.in index 018777efe6..937e67f9dc 100755 --- a/scripts/Aix/nut.init.in +++ b/scripts/Aix/nut.init.in @@ -34,7 +34,7 @@ CLIENT="no" NUT_DIR="@prefix@" NUT_SBIN_DIR="${NUT_DIR}/sbin" NUT_LIB_DIR="${NUT_DIR}/lib" -NUT_RUN_DIR="@PIDPATH@/nut" +NUT_RUN_DIR="@ALTPIDPATH@" CONFIG="@CONFPATH@/nut.conf" NUTUSER="@RUN_AS_USER@" NUTGROUP="@RUN_AS_GROUP@" diff --git a/scripts/HP-UX/postinstall.in b/scripts/HP-UX/postinstall.in index 8111b6a43c..8650d2d81d 100644 --- a/scripts/HP-UX/postinstall.in +++ b/scripts/HP-UX/postinstall.in @@ -2,7 +2,7 @@ # directory definitions NUT_DIR="@prefix@" -INSTALLPATH=$NUT_DIR/script +INSTALLPATH="$NUT_DIR/script" CONFIGPATH=/etc/rc.config.d SCRIPTPATH=/sbin/init.d LINKPATH=/sbin/rc3.d @@ -36,13 +36,18 @@ for file in nut.conf ups.conf upsd.conf upsmon.conf upsd.users upssched.conf; do fi done +# make sure that /var/run exists (for privileged processes) +if [ ! -d @PIDPATH@ ] ; then + mkdir -p @PIDPATH@ +fi + # make sure that /var/run/nut exists and has the correct ownerships -if [ ! -d @PIDPATH@/nut ] ; then - mkdir -p @PIDPATH@/nut +if [ ! -d @ALTPIDPATH@ ] ; then + mkdir -p @ALTPIDPATH@ fi -if [ -d @PIDPATH@/nut ] ; then - chown root:nut @PIDPATH@/nut - chmod 770 @PIDPATH@/nut +if [ -d @ALTPIDPATH@ ] ; then + chown root:nut @ALTPIDPATH@ + chmod 770 @ALTPIDPATH@ fi # make sure that /var/state/ups exists and has the correct ownerships diff --git a/scripts/Solaris/nut-server.xml.in b/scripts/Solaris/nut-server.xml.in index 6fd5c9e6aa..00ff9aebea 100644 --- a/scripts/Solaris/nut-server.xml.in +++ b/scripts/Solaris/nut-server.xml.in @@ -130,7 +130,7 @@ - + diff --git a/scripts/Solaris/postinstall.in b/scripts/Solaris/postinstall.in index a6068b490d..96dc63951c 100755 --- a/scripts/Solaris/postinstall.in +++ b/scripts/Solaris/postinstall.in @@ -35,13 +35,18 @@ for file in nut.conf ups.conf upsd.conf upsmon.conf upsd.users upssched.conf nut fi done +# make sure that /var/run exists (for privileged processes) +if [ ! -d "@PIDPATH@" ] ; then + mkdir -p "@PIDPATH@" +fi + # make sure that /var/run/nut exists and has the correct ownerships -if [ ! -d "@PIDPATH@/nut" ] ; then - mkdir -p "@PIDPATH@/nut" +if [ ! -d "@ALTPIDPATH@" ] ; then + mkdir -p "@ALTPIDPATH@" fi -if [ -d "@PIDPATH@/nut" ] ; then - chown "root:@RUN_AS_GROUP@" "@PIDPATH@/nut" - chmod 770 "@PIDPATH@/nut" +if [ -d "@ALTPIDPATH@" ] ; then + chown "root:@RUN_AS_GROUP@" "@ALTPIDPATH@" + chmod 770 "@ALTPIDPATH@" fi # make sure that /var/state/ups exists and has the correct ownerships diff --git a/scripts/Solaris/postremove.in b/scripts/Solaris/postremove.in index dce3f44e84..e1d1babeeb 100755 --- a/scripts/Solaris/postremove.in +++ b/scripts/Solaris/postremove.in @@ -16,4 +16,8 @@ rm -f /etc/rc3.d/K10nut # Remove /var/run/nut -rm -rf "@PIDPATH@/nut" +rm -rf "@ALTPIDPATH@" + +# Remove /var/state/ups + +rm -rf "@STATEPATH@" diff --git a/scripts/Solaris/svc-nut-monitor.in b/scripts/Solaris/svc-nut-monitor.in index a7dd0dc91d..c33b216a08 100755 --- a/scripts/Solaris/svc-nut-monitor.in +++ b/scripts/Solaris/svc-nut-monitor.in @@ -16,7 +16,7 @@ prefix="@prefix@" NUT_DIR="@prefix@" NUT_SBIN_DIR="${NUT_DIR}/sbin" NUT_LIB_DIR="${NUT_DIR}/lib" -NUT_RUN_DIR="@PIDPATH@/nut" +NUT_RUN_DIR="@ALTPIDPATH@" CONFIG="@CONFPATH@/nut.conf" NUTUSER="@RUN_AS_USER@" NUTGROUP="@RUN_AS_GROUP@" @@ -32,6 +32,7 @@ ups_start () { fi # Default rights inspired by NUT scripts/Solaris/postinstall.in + mkdir -p "@PIDPATH@" # (for privileged processes) mkdir -p "$NUT_RUN_DIR" && \ chown "root:$NUTGROUP" "$NUT_RUN_DIR" && \ chmod 770 "$NUT_RUN_DIR" \ diff --git a/scripts/Solaris/svc-nut-server.in b/scripts/Solaris/svc-nut-server.in index 4fa78fab94..1419da7ec9 100755 --- a/scripts/Solaris/svc-nut-server.in +++ b/scripts/Solaris/svc-nut-server.in @@ -19,7 +19,7 @@ NUT_LIB_DIR="${NUT_DIR}/lib" NUT_RUN_DIR="`svcprop -p nut/NUT_RUN_DIR $SMF_FMRI`" \ && [ -n "$NUT_RUN_DIR" ] \ -|| NUT_RUN_DIR="@PIDPATH@/nut" +|| NUT_RUN_DIR="@ALTPIDPATH@" CONFIG="@CONFPATH@/nut.conf" @@ -37,6 +37,7 @@ fi create_run_dir () { # Default rights inspired by NUT scripts/Solaris/postinstall.in + #mkdir -p "@PIDPATH@" # (for privileged processes - not upsd) mkdir -p "$NUT_RUN_DIR" && \ chown "root:$NUTGROUP" "$NUT_RUN_DIR" && \ chmod 770 "$NUT_RUN_DIR" \ From 6fb37eb53fab37b12e55eac207879ea2725bfa92 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:26:19 +0100 Subject: [PATCH 0120/1232] NEWS, UPGRADING: document @ALTPIDPATH@ vs. @PIDPATH@ (and removal of @PIDPATH@/nut ambiguity) [#1712] --- NEWS | 4 ++++ UPGRADING | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/NEWS b/NEWS index 4028c01ada..0767947f29 100644 --- a/NEWS +++ b/NEWS @@ -166,6 +166,10 @@ https://github.com/networkupstools/nut/milestone/8 - some fixes applied to Solaris/illumos packaging and SMF service support [#1554, #1564] + - `configure` script, reference init-script and packaging templates updated + to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the + unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] + - PyNUT.py version bumped to 1.5.0 with some improvements: * `ListClients()` method fixed (was broken in many ways), and is now CI-tested [#549] diff --git a/UPGRADING b/UPGRADING index bb019e5299..708e6a9e8b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -53,6 +53,10 @@ Changes from 2.8.0 to 2.8.1 or explicitly forfeit building the tool (some distro packages missed it quietly in the past) [#1560] +- `configure` script, reference init-script and packaging templates updated + to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the + unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] + - snmp-ups: some subdrivers (addressed using the driver parameter `mibs`) were renamed: 'pw' is now 'eaton_pw_nm2', and 'pxgx_ups' is 'eaton_pxg_ups' From c839a0b1b26592b87f06d95abcef03a7d0a7792f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:30:17 +0100 Subject: [PATCH 0121/1232] configure.ac: use PIDPATH="/run" if it is so on the build system --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 311629bfe3..6f217078f6 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,8 @@ dnl and more specifically that for `upsmon` (running as `root`). dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below dnl for the unprivileged daemons (`upsd`, drivers). PIDPATH="/var/run" +dnl Honour new LFS recommendations if applied on the build system: +AS_IF([test -d "/run"], [PIDPATH="/run"]) dnl Define directory where LIBOBJS replacement functions are AC_CONFIG_LIBOBJ_DIR([common]) From dfdaba487bef12033fd2271ec0913f8f4f09d1ce Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 21:35:12 +0100 Subject: [PATCH 0122/1232] configure.ac: avoid changing permissions of */tmp and /dev/shm with nut-common.tmpfiles --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6f217078f6..d9c2559193 100644 --- a/configure.ac +++ b/configure.ac @@ -3536,7 +3536,7 @@ X @STATEPATH@ EOF AS_IF([test "$STATEPATH" != "$PIDPATH"], [AS_CASE(["${PIDPATH}"], - [*/run], [], dnl Do not intrude into system paths; TODO: add more if appropriate for some Linux distro + [*/run|*/tmp|*/shm], [], dnl Do not intrude into system paths; TODO: add more if appropriate for some Linux distro [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF d @PIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @PIDPATH@ From 32256c9ea9e601e004f3bad4c0b055200fa162d8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 22:10:12 +0100 Subject: [PATCH 0123/1232] configure.ac: try to detect nut_inplace_group and nut_inplace_user from existing configs [#1714] --- configure.ac | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index d9c2559193..875dff218e 100644 --- a/configure.ac +++ b/configure.ac @@ -3073,13 +3073,45 @@ dnl above as data sources for default values if building an in-place replacement AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) - AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], - [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])]) + nut_inplace_group="" + AS_IF([test -d "${udevdir}/rules.d"], + [for F in "${udevdir}/rules.d"/*-nut-*.rules ; do + if test -s "$F" ; then + nut_inplace_group="`grep GROUP= "$F" | head -1 | sed 's,^.* GROUP="*\(.*\)"*.*$,\1,'`" \ + && test -n "`getent group "${nut_inplace_group}"`" \ + && AC_MSG_RESULT([Got from ${F}]) \ + && break \ + || nut_inplace_group="" + fi + done]) + AS_IF([test -n "${nut_inplace_group}"], + [RUN_AS_GROUP="${nut_inplace_group}"], + [AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], + [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])])]) AC_MSG_RESULT([${RUN_AS_GROUP}]) AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) - AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], - [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])]) + nut_inplace_user="" + AS_IF([test -s "${CONFPATH}/upsmon.conf"], + [nut_inplace_user="`grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`" \ + && test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ + || nut_inplace_user=""]) + AS_IF([test -z "${nut_inplace_user}" && test -s "${LIBDIR}/pkgconfig/libupsclient.pc"], + [nut_inplace_user="`grep -E '^ *nutuser=' "${LIBDIR}/pkgconfig/libupsclient.pc" | sed 's,^ *nutuser=,,'`" \ + && test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${LIBDIR}/pkgconfig/libupsclient.pc]) \ + || nut_inplace_user=""]) + AS_IF([test -z "${nut_inplace_user}" && test -s "${LIBDIR}/pkgconfig/libnutclient.pc"], + [nut_inplace_user="`grep -E '^ *nutuser=' "${LIBDIR}/pkgconfig/libnutclient.pc" | sed 's,^ *nutuser=,,'`" \ + && test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${LIBDIR}/pkgconfig/libnutclient.pc]) \ + || nut_inplace_user=""]) + + AS_IF([test -n "${nut_inplace_user}"], + [RUN_AS_USER="${nut_inplace_user}"], + [AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], + [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])])]) AC_MSG_RESULT([${RUN_AS_USER}]) ]) From 5ece666640a4ad49db294723ee48efcfdc7a4cb3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 22:17:02 +0100 Subject: [PATCH 0124/1232] configure.ac: clarify "checking requested X" => default/specified vs "checking setting X" => final value [#1714] --- configure.ac | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 875dff218e..4b707d4b91 100644 --- a/configure.ac +++ b/configure.ac @@ -2098,7 +2098,7 @@ dnl ---------------------------------------------------------------------- NUT_REPORT_SETTING_PATH([Default installation prefix path], PREFIX, "${prefix}", [Default installation prefix path]) -AC_MSG_CHECKING(state path) +AC_MSG_CHECKING(if requested state path) AC_ARG_WITH(statepath, AS_HELP_STRING([--with-statepath=PATH], [path for ups state files (${STATEPATH}, typically /var/state/ups)]), [ @@ -2122,7 +2122,7 @@ dnl /var/run path. This defaults to the STATEPATH since they should be dnl able to write there. dnl -AC_MSG_CHECKING(alt pid path) +AC_MSG_CHECKING(if requested alt pid path) AC_ARG_WITH(altpidpath, AS_HELP_STRING([--with-altpidpath=PATH], [path for NUT driver/upsd .pid files not running as root ()]), [ @@ -2142,7 +2142,7 @@ AC_ARG_WITH(altpidpath, NUT_REPORT_SETTING_PATH([Unprivileged PID file path], ALTPIDPATH, "${ALTPIDPATH}", [Path for pid files of processes not running as root, such as drivers and upsd (usually STATEPATH)]) -AC_MSG_CHECKING(pidpath) +AC_MSG_CHECKING(if requested pidpath) AC_ARG_WITH(pidpath, AS_HELP_STRING([--with-pidpath=PATH], [Path for root-owned .pid files (${PIDPATH}, typically /var/run)]), [ @@ -2159,7 +2159,7 @@ AC_ARG_WITH(pidpath, NUT_REPORT_SETTING_PATH([Privileged PID file path], PIDPATH, "${PIDPATH}", [Path for pid files of processes running as root, such as upsmon]) -AC_MSG_CHECKING(driver path) +AC_MSG_CHECKING(if requested driver path) AC_ARG_WITH(drvpath, AS_HELP_STRING([--with-drvpath=PATH], [where to install UPS drivers (EPREFIX/bin)]), [ @@ -2179,7 +2179,7 @@ eval conftemp=\"${conftemp}\" NUT_REPORT_SETTING_PATH([Driver program path], DRVPATH, "${conftemp}", [Default path for UPS drivers]) -AC_MSG_CHECKING(cgi path) +AC_MSG_CHECKING(if requested cgi path) AC_ARG_WITH(cgipath, AS_HELP_STRING([--with-cgipath=PATH], [where to install CGI programs (EPREFIX/cgi-bin)]), [ @@ -2199,7 +2199,7 @@ eval conftemp=\"${conftemp}\" NUT_REPORT_SETTING_PATH([CGI program path], CGIPATH, "${conftemp}", [Default path for CGI programs]) -AC_MSG_CHECKING(html path) +AC_MSG_CHECKING(if requested html path) AC_ARG_WITH(htmlpath, AS_HELP_STRING([--with-htmlpath=PATH], [where to install HTML files (PREFIX/html)]), [ @@ -3115,7 +3115,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ AC_MSG_RESULT([${RUN_AS_USER}]) ]) -AC_MSG_CHECKING(user to run as) +AC_MSG_CHECKING(if requested user to run as) AC_ARG_WITH(user, AS_HELP_STRING([--with-user=username], [user for programs started as root (${RUN_AS_USER})]), [ @@ -3136,7 +3136,7 @@ AC_ARG_WITH(user, NUT_REPORT_SETTING([User to run as], RUN_AS_USER, "${RUN_AS_USER}", [User to switch to if started as root]) -AC_MSG_CHECKING(group membership of user to run as) +AC_MSG_CHECKING(if requested group membership of user to run as) AC_ARG_WITH(group, AS_HELP_STRING([--with-group=groupname], [group membership of user for programs started as root (${RUN_AS_GROUP})]), [ From 6694956bbcef2b53cb06dedfb0ab631156015a22 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 22:54:53 +0100 Subject: [PATCH 0125/1232] configure.ac: fix inplace sysconfdir detection [#1714] --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4b707d4b91..1bb3358fbe 100644 --- a/configure.ac +++ b/configure.ac @@ -141,9 +141,11 @@ AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GR ) AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ - dnl If there was no custom --sysconfdir=/etc/myNUT passed, try to default - dnl TODO: Smarter ways welcome (e.g. reliably look at configure CLI opts) - AS_IF([test x"${prefix}/etc" = x"${sysconfdir}"], [ + dnl If there was no custom --sysconfdir=/etc/myNUT passed, + dnl try to default it to something from existing deployment. + dnl NOTE: Single-quotes are correct for autotools default, + dnl expanded at runtime (see conftemp tricks below) + AS_IF([test x'${prefix}/etc' = x"${sysconfdir}"], [ AC_MSG_CHECKING([for in-place replacement default sysconfdir (better than '${sysconfdir}')]) dnl TODO: Any more reasonable defaults? Pile them on here :) for D in \ From 471eac8a752274faeabe5300f74d18f64dfb9fb3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Nov 2022 22:57:53 +0100 Subject: [PATCH 0126/1232] configure.ac: comment about nut_inplace_user detection from *.pc files [#1714] --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 1bb3358fbe..d5f99ca649 100644 --- a/configure.ac +++ b/configure.ac @@ -3099,6 +3099,8 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ && test -n "`getent passwd "${nut_inplace_user}"`" \ && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ || nut_inplace_user=""]) + dnl Note: with default short inplace and no prefix, this would look under + dnl /usr/local/ups/lib/pkgconfig which may be irrelevant for packaged setups AS_IF([test -z "${nut_inplace_user}" && test -s "${LIBDIR}/pkgconfig/libupsclient.pc"], [nut_inplace_user="`grep -E '^ *nutuser=' "${LIBDIR}/pkgconfig/libupsclient.pc" | sed 's,^ *nutuser=,,'`" \ && test -n "`getent passwd "${nut_inplace_user}"`" \ From 6697d509647c6f4554094676ebd85089d1db3cd6 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Sun, 27 Nov 2022 22:01:40 +0100 Subject: [PATCH 0127/1232] Fix AX_C___ATTRIBUTE__ configure check to call the right function The function foo is defined in the C fragment, but the func function is undeclared. This avoids relying on an implicit function declaration, a C language feature that was removed in 1999. --- m4/ax_c___attribute__.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/ax_c___attribute__.m4 b/m4/ax_c___attribute__.m4 index 0e952e7841..780bc2bb14 100644 --- a/m4/ax_c___attribute__.m4 +++ b/m4/ax_c___attribute__.m4 @@ -67,7 +67,7 @@ AC_DEFUN([AX_C___ATTRIBUTE__], [ foo(__attribute__ ((unused)) int i) { return; } - ]], [func(1);])], + ]], [foo(1);])], [ax_cv___attribute__unused_arg=yes], [ax_cv___attribute__unused_arg=no] ) From ac02141585d39ac203aae838447bc1c8b49415b9 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Sun, 27 Nov 2022 22:06:34 +0100 Subject: [PATCH 0128/1232] Fix several issues with the AX_C_PRINTF_STRING_NULL check Adjust quoting in the AX_C_PRINTF_STRING_NULL definition. Switch to strstr and include instead of . Add missing braces and parentheses. Use double-quote for string literals. The test now reports success on glibc, as expected. --- m4/ax_c_pragmas.m4 | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index 7de2c9f00c..14ecd596d3 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -943,32 +943,32 @@ if test -z "${nut_have_ax_c_printf_string_null_seen}"; then dnl ### To be sure, bolt the language AC_LANG_PUSH([C]) - AC_CACHE_CHECK([for practical support to pritnf("%s", NULL)], + AC_CACHE_CHECK([for practical support to printf("%s", NULL)], [ax_cv__printf_string_null], [AX_RUN_OR_LINK_IFELSE( [AC_LANG_PROGRAM([dnl #include -#include -], [dnl +#include +], [[ char buf[128]; char *s = NULL; int res = snprintf(buf, sizeof(buf), "%s", s); buf[sizeof(buf)-1] = '\0'; if (res < 0) { - printf(stderr, "FAILED to snprintf() a NULL string argument"); - exit 1; + fprintf(stderr, "FAILED to snprintf() a NULL string argument\n"); + return 1; } -if (buf[0] == '\0') - printf(stderr, "RETURNED empty string from snprintf() with a NULL string argument"); - exit 0; +if (buf[0] == '\0') { + fprintf(stderr, "RETURNED empty string from snprintf() with a NULL string argument\n"); + return 0; } -if (strcasecmp(buf, 'null') == NULL) - printf(stderr, "RETURNED some string from snprintf() with a NULL string argument: '%s'", buf); - exit 0; +if (strstr(buf, "null") == NULL) { + fprintf(stderr, "RETURNED some string from snprintf() with a NULL string argument: '%s'\n", buf); + return 0; } -printf(stderr, "SUCCESS: RETURNED a string that contains something like 'null' from snprintf() with a NULL string argument: '%s'", buf); -exit 0; - ])], +fprintf(stderr, "SUCCESS: RETURNED a string that contains something like 'null' from snprintf() with a NULL string argument: '%s'\n", buf); +return 0; + ]])], [ax_cv__printf_string_null=yes], [ax_cv__printf_string_null=no] )] From e37d81e04da93c21e8c78c123de2b9e7362e5fdd Mon Sep 17 00:00:00 2001 From: Tiph Date: Mon, 28 Nov 2022 22:55:46 +0100 Subject: [PATCH 0129/1232] Update mge-hid.c fixed conversion issue --- drivers/mge-hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 616579f736..798e64fd28 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -687,7 +687,7 @@ static const char *eaton_compute_realpower_fun(double value) ups_load = atoi(str_ups_load); power_nominal = atoi(str_power_nominal); if (str_powerfactor) - powerfactor = atoi(str_powerfactor); + powerfactor = atof(str_powerfactor); /* Compute the value */ realpower = round(ups_load * 0.01 * power_nominal * powerfactor); snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.0f", realpower); From 089925fff66448877b9a8bd4c24be36a5c8be398 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 15:22:02 +0100 Subject: [PATCH 0130/1232] NEWS, UPGRADING: reference GitHub PR numbers for snmp-ups updates [#1715, #1716] --- NEWS | 8 ++++---- UPGRADING | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index a04088816e..506a175623 100644 --- a/NEWS +++ b/NEWS @@ -121,11 +121,11 @@ https://github.com/networkupstools/nut/milestone/8 * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item in the middle has a type error [#1682] * Better manage the slight nuances (especially in ups.status) between - Eaton UPSs, and rename mibs from 'pw' to 'eaton_pw_nm2', and from - 'pxgx_ups' to 'eaton_pxg_ups' + Eaton UPSs, and rename mibs from `pw` to `eaton_pw_nm2`, and from + `pxgx_ups` to `eaton_pxg_ups` [#1715] * Fixed the long standing "Warning: excessive poll failures" issue, that - was tied to non-existent OIDs, not well handled in some part of the driver - + was tied to non-existent OIDs, not well handled in some parts of the + driver [#1716] - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] diff --git a/UPGRADING b/UPGRADING index 708e6a9e8b..dc77cd25ec 100644 --- a/UPGRADING +++ b/UPGRADING @@ -58,7 +58,8 @@ Changes from 2.8.0 to 2.8.1 unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] - snmp-ups: some subdrivers (addressed using the driver parameter `mibs`) - were renamed: 'pw' is now 'eaton_pw_nm2', and 'pxgx_ups' is 'eaton_pxg_ups' + were renamed: `pw` is now `eaton_pw_nm2`, and `pxgx_ups` is `eaton_pxg_ups` + [#1715] Changes from 2.7.4 to 2.8.0 --------------------------- From 723086c269e21d26df0415fefc57b49e21d68310 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 15:31:35 +0100 Subject: [PATCH 0131/1232] common/common.c: become_user(): cosmetic/messaging: discern starting as not-root vs. already the requested user [#1718] Closes: #1718 --- common/common.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/common/common.c b/common/common.c index e7171d8fb0..443d25d67e 100644 --- a/common/common.c +++ b/common/common.c @@ -268,14 +268,26 @@ void become_user(struct passwd *pw) { #ifndef WIN32 /* if we can't switch users, then don't even try */ - if ((geteuid() != 0) && (getuid() != 0)) { - upsdebugx(1, "Can not become_user(%s): not root initially, " - "remaining UID=%jd GID=%jd", - pw->pw_name, (intmax_t)getuid(), (intmax_t)getgid()); + intmax_t initial_uid = getuid(); + intmax_t initial_euid = geteuid(); + if ((initial_euid != 0) && (initial_uid != 0)) { + intmax_t initial_gid = getgid(); + if (initial_euid == (intmax_t)pw->pw_uid + || initial_uid == (intmax_t)pw->pw_uid + ) { + upsdebugx(1, "No need to become_user(%s): " + "already UID=%jd GID=%jd", + pw->pw_name, initial_uid, initial_gid); + } else { + upsdebugx(1, "Can not become_user(%s): " + "not root initially, " + "remaining UID=%jd GID=%jd", + pw->pw_name, initial_uid, initial_gid); + } return; } - if (getuid() == 0) + if (initial_uid == 0) if (seteuid(0)) fatal_with_errno(EXIT_FAILURE, "getuid gave 0, but seteuid(0) failed"); From ce7a01d7d8fbe8a7883975bf977637d662db1e53 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 15:51:57 +0100 Subject: [PATCH 0132/1232] Create codeql.yml LGTM.com is being deprecated in favor of equivalent GitHub Action by same team * https://github.blog/2022-08-15-the-next-step-for-lgtm-com-github-code-scanning/ * https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository#setting-up-code-scanning-manually --- .github/workflows/codeql.yml | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..6bdaba8481 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,74 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '32 12 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp', 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" From df6e64045798bda6a24f45c7c8356366db3881ed Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 16:12:43 +0100 Subject: [PATCH 0133/1232] Update codeql.yml Drop python for now --- .github/workflows/codeql.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6bdaba8481..a9868e7013 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,9 +32,10 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp', 'python' ] + language: [ 'cpp' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + # TODO: Want to find Python sources to test like with LGTM, see https://github.com/networkupstools/nut/issues/1726 steps: - name: Checkout repository From e62023397a84c0fc667c93dbf2f2c315c30a32a6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 10:13:47 +0100 Subject: [PATCH 0134/1232] scripts/systemd/nut-server.service.in: re-document use of PID file, for reloads to work [#1721] --- scripts/systemd/nut-server.service.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 713f5c4273..5edc2d5fa4 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -20,8 +20,9 @@ PartOf=nut.target [Service] EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N -# Note: foreground mode by default skips writing a PID file (and -# needs Type=simple); can use "-FF" here to create one anyway: +# Note: foreground mode "-F" by default skips writing a PID file (and +# needs default Type=simple); we can use "-FF" here to create the file +# anyway, so that old "upsd -c reload" works rather than systemd action: ExecStart=@SBINDIR@/upsd -F ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID From d9875fad3d740075b619f2a32013150aed579d7d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 10:46:36 +0100 Subject: [PATCH 0135/1232] configure.ac: refactor definition of HAVE_SYSTEMD so we can use it in C code [#1721] --- configure.ac | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d5f99ca649..4ee8734e36 100644 --- a/configure.ac +++ b/configure.ac @@ -2506,11 +2506,17 @@ case "${systemdsystemunitdir}" in esac if test "${systemdsystemunitdir}" = "auto" ; then systemdsystemunitdir=""; fi if test -n "${systemdsystemunitdir}"; then + have_systemd="yes" AC_MSG_RESULT(using ${systemdsystemunitdir}) else + have_systemd="no" AC_MSG_RESULT(no) fi -AM_CONDITIONAL(HAVE_SYSTEMD, test "$systemdsystemunitdir" != "") +dnl Note: we may want tighter integration, e.g. systemd-notify support at +dnl a later point. That would be a further option/flag. This one is a very +dnl basic yes/no toggle. +NUT_REPORT_FEATURE([consider systemd support], [${have_systemd}], [], + [HAVE_SYSTEMD], [Define to consider systemd support]) dnl This option is only provided so that make distcheck can override it, dnl otherwise we ask pkg-config whenever --with-systemdsystemunitdir is dnl given From 6df230c2e5683c4f698026384fe7cbbd0fdc54bf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 10:57:16 +0100 Subject: [PATCH 0136/1232] server/upsd.c: consider HAVE_SYSTEMD to report if PID file was missing [#1721] --- server/upsd.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/server/upsd.c b/server/upsd.c index f0ce3f24e1..a7d3f4bb8b 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -159,6 +159,9 @@ static int reload_flag = 0, exit_flag = 0; /* Ref: RFC 4122 https://tools.ietf.org/html/rfc4122#section-4.1.2 */ #define UUID4_BYTESIZE 16 +#ifdef HAVE_SYSTEMD +# define SERVICE_UNIT_NAME "nut-server.service" +#endif static const char *inet_ntopW (struct sockaddr_storage *s) { @@ -1690,6 +1693,32 @@ int main(int argc, char **argv) } else { cmdret = sendsignalpid(oldpid, cmd); } + +# ifdef HAVE_SYSTEMD + if (cmdret != 0) { + switch (cmd) { + case SIGCMD_RELOAD: + upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_STOP: + upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + default: + upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + } + /* ... or edit nut-server.service locally to start `upsd -FF` + * and so save the PID file for ability to manage the daemon + * beside the service framework, possibly confusing things... + */ + } +# endif #else cmdret = sendsignal(UPSD_PIPE_NAME, cmd); #endif From 8e13e3e7a75c0d93e09314b0982d5638c5e9c943 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 11:12:53 +0100 Subject: [PATCH 0137/1232] clients/upsmon.c: consider HAVE_SYSTEMD to report if PID file was missing [#1721] --- clients/upsmon.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/clients/upsmon.c b/clients/upsmon.c index e7124a42a7..d295e3b772 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -104,6 +104,10 @@ static struct sigaction sa; static sigset_t nut_upsmon_sigmask; #endif +#ifdef HAVE_SYSTEMD +# define SERVICE_UNIT_NAME "nut-monitor.service" +#endif + /* Users can pass a -D[...] option to enable debugging. * For the service tracing purposes, also the upsmon.conf * can define a debug_min value in the global section, @@ -2373,6 +2377,33 @@ int main(int argc, char *argv[]) } else { cmdret = sendsignalpid(oldpid, cmd); } + +# ifdef HAVE_SYSTEMD + if (cmdret != 0) { + switch (cmd) { + case SIGCMD_RELOAD: + upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_STOP: + upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_FSD: + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } + break; + default: + upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + } + } +# endif #else cmdret = sendsignal(UPSMON_PIPE_NAME, cmd); #endif From b2ce138e2b794a9a9464a56cca065f3742217bde Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 11:30:30 +0100 Subject: [PATCH 0138/1232] conf/*.sample: standardize on "monuser" as example NUT-defined account for upsmon [#1721] --- conf/ups.conf.sample | 4 ++-- conf/upsd.users.sample | 6 +++--- conf/upsmon.conf.sample.in | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/conf/ups.conf.sample b/conf/ups.conf.sample index 3cc7ccb0bd..dba6d92fbf 100644 --- a/conf/ups.conf.sample +++ b/conf/ups.conf.sample @@ -32,12 +32,12 @@ # On a system called "doghouse", the line in your upsmon.conf to monitor # and manage it would look something like this: # -# MONITOR snoopy@doghouse 1 upsmonuser mypassword primary +# MONITOR snoopy@doghouse 1 monuser mypassword primary # # It might look like this if monitoring in "secondary" mode (without any # ability to directly manage the UPS) from a different system: # -# MONITOR snoopy@doghouse 1 upsmonuser mypassword secondary +# MONITOR snoopy@doghouse 1 monuser mypassword secondary # # Configuration directives # ------------------------ diff --git a/conf/upsd.users.sample b/conf/upsd.users.sample index c6b9f36ed7..60c42892bf 100644 --- a/conf/upsd.users.sample +++ b/conf/upsd.users.sample @@ -59,9 +59,9 @@ # # --- Configuring for upsmon # -# To add a user for your upsmon, use this example: +# To add a NUT user for your upsmon, with a particular role, use this example: # -# [upsmon] +# [monuser] # password = pass # upsmon primary # or @@ -69,7 +69,7 @@ # # The matching MONITOR line in your upsmon.conf would look like this: # -# MONITOR myups@localhost 1 upsmon pass primary (or secondary) +# MONITOR myups@localhost 1 monuser pass primary (or secondary) # # See comments in the upsmon.conf(.sample) file for details about this # keyword and the difference of NUT secondary and primary systems. diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 110d0a4f42..62c853b1f1 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -66,10 +66,10 @@ # changes for a given UPS without shutting down when it goes critical. # # and must match an entry in that system's -# upsd.users. If your username is "upsmon" and your password is +# upsd.users. If your NUT username is "monuser" and your password is # "blah", the upsd.users would look like this: # -# [upsmon] +# [monuser] # password = blah # upsmon primary # (or secondary) # @@ -113,8 +113,8 @@ # Examples: # # MONITOR myups@bigserver 1 upswired blah primary -# MONITOR su700@server.example.com 1 upsmon secretpass secondary -# MONITOR myups@localhost 1 upsmon pass primary # (or secondary) +# MONITOR su700@server.example.com 1 monuser secretpass secondary +# MONITOR myups@localhost 1 monuser pass primary # (or secondary) # -------------------------------------------------------------------------- # MINSUPPLIES From cece3f1bbb7d54cccb84c7968221c24868f60ccf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 11:31:15 +0100 Subject: [PATCH 0139/1232] conf/upsmon.conf.sample.in: clarify RUN_AS_USER as OS-defined account for upsmon [#1721] --- conf/upsmon.conf.sample.in | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 62c853b1f1..8e86e00d0c 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -27,6 +27,7 @@ # # This user should not have write access to upsmon.conf. # +# (Unprivileged) OS account to run as: # RUN_AS_USER @RUN_AS_USER@ # -------------------------------------------------------------------------- From b9144c433289faaafcb8b0655167dca505ccf971 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 11:50:21 +0100 Subject: [PATCH 0140/1232] docs/*.txt: clarify "upsd -c reload" vs. PID file (and systemd) [#1721] --- docs/FAQ.txt | 10 +++++++++- docs/config-notes.txt | 8 ++++++-- docs/man/upsd.txt | 5 ++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/FAQ.txt b/docs/FAQ.txt index 9c59f100b4..3c37951881 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -535,13 +535,21 @@ Or a variation like... == How do you make upsd reload the config file? Either find the pid of the background process and send it a SIGHUP, -or just start it again with '-c reload'. +or just start it again with '-c reload' (requires that the previously +started daemon saves a PID file). If you send the signals yourself instead of using -c, be sure you hit the right process. There are usually two upsmon processes, and you should only send signals to one of them. To be safe, read the pid file. +If your daemons are managed as systemd units, it is more idiomatic to +use the framework commands, e.g. `systemctl reload nut-server` (upsd) +or `systemctl reload nut-monitor` (upsmon). Note that the implementation +of `nut-server.service` by default starts `upsd -F` and does not save a +PID file; if your workflow requires to use plain `upsd -c reload`, you +should customize the unit (with a drop-in file) to start `upsd -FF`. + == I just bought a new WhizBang UPS that has a USB connector. How do I monitor it? There are several driver to support USB models. diff --git a/docs/config-notes.txt b/docs/config-notes.txt index c39d67efa9..2e0ab75e02 100644 --- a/docs/config-notes.txt +++ b/docs/config-notes.txt @@ -585,7 +585,8 @@ Reloading the data server ^^^^^^^^^^^^^^^^^^^^^^^^^ Reload `upsd`. Depending on your configuration, you may be able to -do this without stopping the `upsd` daemon process: +do this without stopping the `upsd` daemon process (if it had saved +a PID file earlier): upsd -c reload @@ -596,7 +597,10 @@ If that doesn't work (check the syslog), just restart it: For systems with integrated service management (Linux systemd, illumos/Solaris SMF) their corresponding `reload` or `refresh` -service actions should handle this as well. +service actions should handle this as well. Note that such integration +generally forgoes saving of PID files, so `upsd -c ` would not work. +If your workflow requires to manage these daemons beside the OS provided +framework, you can customize it to start `upsd -FF` and save the PID file. NOTE: If you want to make reloading work later, see the entry in the link:FAQ.html[FAQ] about starting `upsd` as a different user. diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index 25d92ca171..ffdcbcc802 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -87,7 +87,10 @@ RELOADING upsd can reload its configuration files without shutting down the process if you send it a SIGHUP or start it again with `-c reload`. This only works -if the background process is able to read those files. +if the background process is able to read those files, and if the daemon did +save a PID file when it started (e.g. service instances wrapped by systemd +or SMF do not save them by default -- use respective `reload`/`refresh` +framework actions instead). If you think that upsd can't reload, check your syslog for error messages. If it's complaining about not being able to read the files, then you need From 7c7d9211a3b9fe06dd44ae78bb609b546d4171e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Dec 2022 12:01:20 +0100 Subject: [PATCH 0141/1232] common/common.c: clarify inability to find OS user info (vs. NUT user) [#1721] --- common/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 443d25d67e..c8f931ab47 100644 --- a/common/common.c +++ b/common/common.c @@ -229,7 +229,7 @@ struct passwd *get_user_pwent(const char *name) some implementations of getpwnam() do not set errno when this happens. */ if (errno == 0) - fatalx(EXIT_FAILURE, "user %s not found", name); + fatalx(EXIT_FAILURE, "OS user %s not found", name); else fatal_with_errno(EXIT_FAILURE, "getpwnam(%s)", name); #else From 889b42ad966823fce09c6196d3147aaae173386e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Dec 2022 12:54:03 +0100 Subject: [PATCH 0142/1232] server/upsd.c: generic report if we "Failed to signal the currently running daemon" [#1721] --- server/upsd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/upsd.c b/server/upsd.c index a7d3f4bb8b..933d51d27b 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1687,6 +1687,7 @@ int main(int argc, char **argv) } if (cmd) { + int reported = 0; #ifndef WIN32 if (oldpid < 0) { cmdret = sendsignalfn(pidfn, cmd); @@ -1717,11 +1718,23 @@ int main(int argc, char **argv) * and so save the PID file for ability to manage the daemon * beside the service framework, possibly confusing things... */ + reported = 1; } # endif #else cmdret = sendsignal(UPSD_PIPE_NAME, cmd); #endif + + if (cmdret != 0 && !reported) { + /* sendsignal*() above might have logged more details + * for troubleshooting, e.g. about lack of PID file + */ + upslogx(LOG_NOTICE, "Failed to signal the currently running daemon"); + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } + } + exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); } From 1a416f0354e38f5f61403fbcc3b30fe8baf79e3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Dec 2022 13:48:58 +0100 Subject: [PATCH 0143/1232] clients/upsmon.c: generic report if we "Failed to signal the currently running daemon" [#1721] --- clients/upsmon.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/clients/upsmon.c b/clients/upsmon.c index d295e3b772..a00d20e87d 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2371,6 +2371,7 @@ int main(int argc, char *argv[]) } if (cmd) { + int reported = 0; #ifndef WIN32 if (oldpid < 0) { cmdret = sendsignal(prog, cmd); @@ -2402,11 +2403,23 @@ int main(int argc, char *argv[]) (oldpid < 0 ? " or add '-P $PID' argument" : "")); break; } + reported = 1; } # endif #else cmdret = sendsignal(UPSMON_PIPE_NAME, cmd); #endif + + if (cmdret != 0 && !reported) { + /* sendsignal*() above might have logged more details + * for troubleshooting, e.g. about lack of PID file + */ + upslogx(LOG_NOTICE, "Failed to signal the currently running daemon"); + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } + } + /* exit(EXIT_SUCCESS); */ exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); } From ad5cc16d54e815ba96ba854452ed4778c9c91e97 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Dec 2022 14:35:53 +0100 Subject: [PATCH 0144/1232] server/upsd.c: refactor probing/signaling old instance into one handling/reporting codebase [#1721] --- server/upsd.c | 158 +++++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 71 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 933d51d27b..3c926a53e1 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1686,92 +1686,66 @@ int main(int argc, char **argv) } } - if (cmd) { - int reported = 0; + /* Note: "cmd" may be non-trivial to command that instance by + * explicit PID number or lookup in PID file (error if absent). + * Otherwise, we are being asked to start and "cmd" is 0/NULL - + * for probing whether a competing older instance of this program + * is running (error if it is). + */ #ifndef WIN32 - if (oldpid < 0) { - cmdret = sendsignalfn(pidfn, cmd); - } else { - cmdret = sendsignalpid(oldpid, cmd); - } + /* If cmd == 0 we are starting and check if a previous instance + * is running by sending signal '0' (i.e. 'kill 0' equivalent) + */ -# ifdef HAVE_SYSTEMD - if (cmdret != 0) { - switch (cmd) { - case SIGCMD_RELOAD: - upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - case SIGCMD_STOP: - upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - default: - upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - } - /* ... or edit nut-server.service locally to start `upsd -FF` - * and so save the PID file for ability to manage the daemon - * beside the service framework, possibly confusing things... - */ - reported = 1; - } -# endif -#else + if (oldpid < 0) { + cmdret = sendsignalfn(pidfn, cmd); + } else { + cmdret = sendsignalpid(oldpid, cmd); + } +#else /* if WIN32 */ + if (cmd) { + /* Command the running daemon, it should be there */ cmdret = sendsignal(UPSD_PIPE_NAME, cmd); -#endif - - if (cmdret != 0 && !reported) { - /* sendsignal*() above might have logged more details - * for troubleshooting, e.g. about lack of PID file - */ - upslogx(LOG_NOTICE, "Failed to signal the currently running daemon"); - if (oldpid < 0) { - upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } else { + /* Starting new daemon, check for competition */ + mutex = CreateMutex(NULL, TRUE, UPSD_PIPE_NAME); + if (mutex == NULL) { + if (GetLastError() != ERROR_ACCESS_DENIED) { + fatalx(EXIT_FAILURE, + "Can not create mutex %s : %d.\n", + UPSD_PIPE_NAME, (int)GetLastError()); } } - exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); - } - - /* otherwise, we are being asked to start. - * so check if a previous instance is running by sending signal '0' - * (Ie 'kill 0') */ -#ifndef WIN32 - if (oldpid < 0) { - cmdret = sendsignalfn(pidfn, 0); - } else { - cmdret = sendsignalpid(oldpid, 0); - } -#else - mutex = CreateMutex(NULL,TRUE,UPSD_PIPE_NAME); - if (mutex == NULL) { - if (GetLastError() != ERROR_ACCESS_DENIED) { - fatalx(EXIT_FAILURE, "Can not create mutex %s : %d.\n",UPSD_PIPE_NAME,(int)GetLastError()); + cmdret = -1; /* unknown, maybe ok */ + if (GetLastError() == ERROR_ALREADY_EXISTS + || GetLastError() == ERROR_ACCESS_DENIED + ) { + cmdret = 0; /* known conflict */ } } - - cmdret = -1; /* unknown, maybe ok */ - if (GetLastError() == ERROR_ALREADY_EXISTS - || GetLastError() == ERROR_ACCESS_DENIED) - cmdret = 0; /* known conflict */ -#endif +#endif /* WIN32 */ switch (cmdret) { case 0: - printf("Fatal error: A previous upsd instance is already running!\n"); - printf("Either stop the previous instance first, or use the 'reload' command.\n"); - exit(EXIT_FAILURE); + if (cmd) { + upsdebugx(1, "Signaled old daemon OK"); + } else { + printf("Fatal error: A previous upsd instance is already running!\n"); + printf("Either stop the previous instance first, or use the 'reload' command.\n"); + exit(EXIT_FAILURE); + } + break; case -3: case -2: + /* if starting new daemon, no competition running - + * maybe OK (or failed to detect it => problem) + * if signaling old daemon - certainly have a problem + */ upslogx(LOG_WARNING, "Could not %s PID file '%s' " "to see if previous upsd instance is " - "already running!\n", + "already running!", (cmdret == -3 ? "find" : "parse"), pidfn); break; @@ -1779,10 +1753,52 @@ int main(int argc, char **argv) case -1: case 1: /* WIN32 */ default: - /* Just failed to send signal, no competitor running */ + /* if cmd was nontrivial - speak up below, else be quiet */ + upsdebugx(1, "Just failed to send signal, no daemon was running"); break; } + if (cmd) { + /* We were signalling a daemon, successfully or not - exit now... */ + if (cmdret != 0) { + /* sendsignal*() above might have logged more details + * for troubleshooting, e.g. about lack of PID file + */ + upslogx(LOG_NOTICE, "Failed to signal the currently running daemon (if any)"); +#ifndef WIN32 +# ifdef HAVE_SYSTEMD + switch (cmd) { + case SIGCMD_RELOAD: + upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_STOP: + upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + default: + upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + } + /* ... or edit nut-server.service locally to start `upsd -FF` + * and so save the PID file for ability to manage the daemon + * beside the service framework, possibly confusing things... + */ +# else + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } +# endif +#endif /* not WIN32 */ + } + + exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); + } + argc -= optind; argv += optind; From c78e889c4d29e30223379fdea1f1cc08625bb02d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Dec 2022 14:51:23 +0100 Subject: [PATCH 0145/1232] clients/upsmon.c: refactor probing/signaling old instance into one handling/reporting codebase [#1721] --- clients/upsmon.c | 161 ++++++++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 72 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index a00d20e87d..fd9a560516 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2370,102 +2370,119 @@ int main(int argc, char *argv[]) } } - if (cmd) { - int reported = 0; + /* Note: "cmd" may be non-trivial to command that instance by + * explicit PID number or lookup in PID file (error if absent). + * Otherwise, we are being asked to start and "cmd" is 0/NULL - + * for probing whether a competing older instance of this program + * is running (error if it is). + */ #ifndef WIN32 - if (oldpid < 0) { - cmdret = sendsignal(prog, cmd); - } else { - cmdret = sendsignalpid(oldpid, cmd); - } + /* If cmd == 0 we are starting and check if a previous instance + * is running by sending signal '0' (i.e. 'kill 0' equivalent) + */ + if (oldpid < 0) { + cmdret = sendsignal(prog, cmd); + } else { + cmdret = sendsignalpid(oldpid, cmd); + } -# ifdef HAVE_SYSTEMD - if (cmdret != 0) { - switch (cmd) { - case SIGCMD_RELOAD: - upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - case SIGCMD_STOP: - upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - case SIGCMD_FSD: - if (oldpid < 0) { - upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); - } - break; - default: - upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", - SERVICE_UNIT_NAME, - (oldpid < 0 ? " or add '-P $PID' argument" : "")); - break; - } - reported = 1; - } -# endif -#else +#else /* WIN32 */ + if (cmd) { + /* Command the running daemon, it should be there */ cmdret = sendsignal(UPSMON_PIPE_NAME, cmd); -#endif - - if (cmdret != 0 && !reported) { - /* sendsignal*() above might have logged more details - * for troubleshooting, e.g. about lack of PID file - */ - upslogx(LOG_NOTICE, "Failed to signal the currently running daemon"); - if (oldpid < 0) { - upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } else { + /* Starting new daemon, check for competition */ + mutex = CreateMutex(NULL, TRUE, UPSMON_PIPE_NAME); + if (mutex == NULL) { + if (GetLastError() != ERROR_ACCESS_DENIED) { + fatalx(EXIT_FAILURE, + "Can not create mutex %s : %d.\n", + UPSMON_PIPE_NAME, (int)GetLastError()); } } - /* exit(EXIT_SUCCESS); */ - exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); - } - - /* otherwise, we are being asked to start. - * so check if a previous instance is running by sending signal '0' - * (Ie 'kill 0') */ -#ifndef WIN32 - if (oldpid < 0) { - cmdret = sendsignal(prog, 0); - } else { - cmdret = sendsignalpid(oldpid, 0); - } -#else - mutex = CreateMutex(NULL,TRUE,UPSMON_PIPE_NAME); - if(mutex == NULL ) { - if( GetLastError() != ERROR_ACCESS_DENIED ) { - fatalx(EXIT_FAILURE, "Can not create mutex %s : %d.\n",UPSMON_PIPE_NAME,(int)GetLastError()); + cmdret = -1; /* unknown, maybe ok */ + if (GetLastError() == ERROR_ALREADY_EXISTS + || GetLastError() == ERROR_ACCESS_DENIED + ) { + cmdret = 0; /* known conflict */ } } - - cmdret = -1; /* unknown, maybe ok */ - if (GetLastError() == ERROR_ALREADY_EXISTS || GetLastError() == ERROR_ACCESS_DENIED) - cmdret = 0; /* known conflict */ -#endif +#endif /* WIN32 */ switch (cmdret) { case 0: - printf("Fatal error: A previous upsmon instance is already running!\n"); - printf("Either stop the previous instance first, or use the 'reload' command.\n"); - exit(EXIT_FAILURE); + if (cmd) { + upsdebugx(1, "Signaled old daemon OK"); + } else { + printf("Fatal error: A previous upsmon instance is already running!\n"); + printf("Either stop the previous instance first, or use the 'reload' command.\n"); + exit(EXIT_FAILURE); + } + break; case -3: case -2: + /* if starting new daemon, no competition running - + * maybe OK (or failed to detect it => problem) + * if signaling old daemon - certainly have a problem + */ upslogx(LOG_WARNING, "Could not %s PID file " "to see if previous upsmon instance is " - "already running!\n", + "already running!", (cmdret == -3 ? "find" : "parse")); break; case -1: + case 1: /* WIN32 */ default: - /* Just failed to send signal, no competitor running */ + /* if cmd was nontrivial - speak up below, else be quiet */ + upsdebugx(1, "Just failed to send signal, no daemon was running"); break; } + if (cmd) { + /* We were signalling a daemon, successfully or not - exit now... */ + if (cmdret != 0) { + /* sendsignal*() above might have logged more details + * for troubleshooting, e.g. about lack of PID file + */ + upslogx(LOG_NOTICE, "Failed to signal the currently running daemon (if any)"); +#ifndef WIN32 +# ifdef HAVE_SYSTEMD + switch (cmd) { + case SIGCMD_RELOAD: + upslogx(LOG_NOTICE, "Try 'systemctl reload %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_STOP: + upslogx(LOG_NOTICE, "Try 'systemctl stop %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + case SIGCMD_FSD: + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } + break; + default: + upslogx(LOG_NOTICE, "Try 'systemctl %s'%s", + SERVICE_UNIT_NAME, + (oldpid < 0 ? " or add '-P $PID' argument" : "")); + break; + } +# else + if (oldpid < 0) { + upslogx(LOG_NOTICE, "Try to add '-P $PID' argument"); + } +# endif +#endif /* not WIN32 */ + } + + exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); + } + argc -= optind; argv += optind; From 8e24bb11d6c68c88da4427ea5d0ce892f4bd13f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 6 Sep 2022 11:21:21 +0200 Subject: [PATCH 0146/1232] drivers/libhid.c: log if we hit the "paranoia check" with inconsistent Max vs Min [#1512] --- drivers/libhid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/libhid.c b/drivers/libhid.c index 6cd2052359..ef033179b4 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -819,6 +819,7 @@ static double logical_to_physical(HIDData_t *Data, long logical) if ((Data->PhyMax <= Data->PhyMin) || (Data->LogMax <= Data->LogMin)) { /* this should not really happen */ + upsdebugx(5, "Max was not greater than Min, returning logical value as is"); return (double)logical; } @@ -857,6 +858,7 @@ static long physical_to_logical(HIDData_t *Data, double physical) if ((Data->PhyMax <= Data->PhyMin) || (Data->LogMax <= Data->LogMin)) { /* this should not really happen */ + upsdebugx(5, "Max was not greater than Min, returning physical value as is"); return (long)physical; } From 73a35d038d4a0c012a8f8134d83ed827956c113d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 6 Sep 2022 14:14:44 +0200 Subject: [PATCH 0147/1232] drivers/main.c: retain "driver.parameter.override.XXX" (and ".default.XXX") for troubleshooting [#1279] --- drivers/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 8f7dce69cd..33c16de860 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -205,13 +205,17 @@ static void storeval(const char *var, char *val) vartab_t *tmp, *last; if (!strncasecmp(var, "override.", 9)) { + /* NOTE: No regard for VAR_SENSITIVE here */ dstate_setinfo(var+9, "%s", val); dstate_setflags(var+9, ST_FLAG_IMMUTABLE); + dparam_setinfo(var, val); return; } if (!strncasecmp(var, "default.", 8)) { + /* NOTE: No regard for VAR_SENSITIVE here */ dstate_setinfo(var+8, "%s", val); + dparam_setinfo(var, val); return; } From 0f08cfdf531648a2515f728ef87aadad3011d09e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 6 Sep 2022 15:23:21 +0200 Subject: [PATCH 0148/1232] drivers/nutdrv_qx.c: qx_initbattery(): initialize battery.packs and battery.voltage.low/high/nom if known always (not just if battery.charge or battery.runtime are not served) [#1279] --- drivers/nutdrv_qx.c | 72 ++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 414318730e..ba98f7b815 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -275,52 +275,58 @@ static int qx_load(void) return 0; } -/* Guesstimation: init */ +/* Init known (readings, configs) and guessed (if needed) battery related values */ static void qx_initbattery(void) { - if (!dstate_getinfo("battery.charge") || !dstate_getinfo("battery.runtime")) { + const char *val; + int batt_packs_known = 0; - const char *val; + val = dstate_getinfo("battery.voltage.high"); + if (val) { + batt.volt.high = strtod(val, NULL); + } - val = dstate_getinfo("battery.voltage.high"); - if (val) { - batt.volt.high = strtod(val, NULL); - } + val = dstate_getinfo("battery.voltage.low"); + if (val) { + batt.volt.low = strtod(val, NULL); + } - val = dstate_getinfo("battery.voltage.low"); - if (val) { - batt.volt.low = strtod(val, NULL); - } + val = dstate_getinfo("battery.voltage.nominal"); + if (val) { + batt.volt.nom = strtod(val, NULL); + } - val = dstate_getinfo("battery.voltage.nominal"); - if (val) { - batt.volt.nom = strtod(val, NULL); - } + /* If no values are available for both battery.voltage.{low,high} + * either from the UPS or provided by the user in ups.conf, + * but nominal battery.voltage.nom is known, + * try to guesstimate them, but announce it! */ + if ( (!d_equal(batt.volt.nom, -1)) && (d_equal(batt.volt.low, -1) || d_equal(batt.volt.high, -1))) { - /* If no values are available for both battery.voltage.{low,high} - * either from the UPS or provided by the user in ups.conf, - * try to guesstimate them, but announce it! */ - if ( (!d_equal(batt.volt.nom, -1)) && (d_equal(batt.volt.low, -1) || d_equal(batt.volt.high, -1))) { + upslogx(LOG_INFO, "No values for battery high/low voltages"); - upslogx(LOG_INFO, "No values for battery high/low voltages"); + /* Basic formula, which should cover most cases */ + batt.volt.low = 104 * batt.volt.nom / 120; + batt.volt.high = 130 * batt.volt.nom / 120; - /* Basic formula, which should cover most cases */ - batt.volt.low = 104 * batt.volt.nom / 120; - batt.volt.high = 130 * batt.volt.nom / 120; + /* Publish these data too */ + dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low); + dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high); - /* Publish these data too */ - dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low); - dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high); + upslogx(LOG_INFO, "Using 'guesstimation' (low: %f, high: %f)!", + batt.volt.low, batt.volt.high); - upslogx(LOG_INFO, "Using 'guesstimation' (low: %f, high: %f)!", - batt.volt.low, batt.volt.high); + } - } + val = dstate_getinfo("battery.packs"); + if (val && (strspn(val, "0123456789 .") == strlen(val))) { + batt.packs = strtod(val, NULL); + batt_packs_known = 1; + } - val = dstate_getinfo("battery.packs"); - if (val && (strspn(val, "0123456789 .") == strlen(val))) { - batt.packs = strtod(val, NULL); - } else { + /* Guesstimation: init values if not provided by device/overrides */ + if (!dstate_getinfo("battery.charge") || !dstate_getinfo("battery.runtime")) { + + if (!batt_packs_known) { /* qx_battery -> batt.volt.act */ if (!qx_battery() && (!d_equal(batt.volt.nom, -1))) { From 2852d6637eb01b81b084f872cbef66cad9690b8e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 14 Sep 2022 12:03:06 +0200 Subject: [PATCH 0149/1232] configure.ac: comment that _GNU_SOURCE may be needed for strptime() detection --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4ee8734e36..2ef8533337 100644 --- a/configure.ac +++ b/configure.ac @@ -461,8 +461,10 @@ if (p == NULL || *p != '\0') return 1])], )]) AS_IF([test x"${ac_cv_func_strptime}" = xyes], [AC_DEFINE([HAVE_STRPTIME], 1, [defined if standard library has, and C standard allows, the strptime(s1,s2) method])], - [AC_MSG_WARN([Optional C library routine strptime not found; a fallback implementation will be built in])] + [AC_MSG_WARN([Optional C library routine strptime not found; try adding _GNU_SOURCE; a fallback implementation will be built in])] ) +dnl Note: per Linux headers, this may need __USE_XOPEN (features.h) +dnl which is enabled by _XOPEN_SOURCE via _GNU_SOURCE on the platform. AM_CONDITIONAL([HAVE_STRPTIME], [test x"${ac_cv_func_strptime}" = "xyes"]) AC_CACHE_CHECK([for strdup(s)], From e0b3e9cf595863a345caec99e2c40b0bbf64ff76 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 17:51:13 +0200 Subject: [PATCH 0150/1232] drivers/nutdrv_qx.c: bump DRIVER_VERSION for issue #1279 changes --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index ba98f7b815..cc085c2dc8 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -38,7 +38,7 @@ * */ -#define DRIVER_VERSION "0.32" +#define DRIVER_VERSION "0.33" #include "config.h" #include "main.h" From eb28a1dfcbb56e6b671011ad1364b25de182f8e0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 18:38:16 +0200 Subject: [PATCH 0151/1232] nutdrv_qx: introduce a "battery_voltage_reports_one_pack" driver option [#1279] --- NEWS | 3 ++ docs/man/nutdrv_qx.txt | 30 ++++++++++++++++-- docs/nut.dict | 3 +- drivers/nutdrv_qx.c | 53 ++++++++++++++++++++++++++++++-- drivers/nutdrv_qx.h | 3 ++ drivers/nutdrv_qx_bestups.c | 4 +-- drivers/nutdrv_qx_hunnox.c | 4 +-- drivers/nutdrv_qx_mecer.c | 4 +-- drivers/nutdrv_qx_megatec-old.c | 4 +-- drivers/nutdrv_qx_megatec.c | 4 +-- drivers/nutdrv_qx_mustek.c | 4 +-- drivers/nutdrv_qx_q1.c | 4 +-- drivers/nutdrv_qx_voltronic-qs.c | 4 +-- drivers/nutdrv_qx_voltronic.c | 4 +-- drivers/nutdrv_qx_zinto.c | 4 +-- 15 files changed, 106 insertions(+), 26 deletions(-) diff --git a/NEWS b/NEWS index 506a175623..331b216be2 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,9 @@ https://github.com/networkupstools/nut/milestone/8 for auto-detection [#1448, #1684] - nutdrv_qx updates: + * a `battery_voltage_reports_one_pack` driver option was added for devices + which "natively" report a `battery.voltage` for a single battery pack or + cell, not for the whole assembly [#1279] * the `voltronic_qs_protocol` should now accept both "V" (as before) and newly "H" dialects, which otherwise seem interchangeable [#1623] diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index d46e3c510b..dcf9a34d20 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -88,9 +88,33 @@ If you want the driver to report a guesstimated *battery.charge*, you need to sp Some devices show a wrong nominal battery voltage (or none at all), so you may need to override or set a default value. *override.battery.packs =* 'value':: -Some devices report a part of the total battery voltage. -For instance, if *battery.voltage.nominal* is 24 V, but it reports a *battery.voltage* of around 2 V, the number of *battery.packs* to correct this reading would be 12. -The driver will attempt to detect this automatically, but if this fails somehow, you may want to override this value. +Some devices "natively" report just a part of the total battery voltage +(see also *battery_voltage_reports_one_pack* below). ++ +For instance, if *battery.voltage.nominal* is 24 V, but it reports +a *battery.voltage* of around 2 V, the number of *battery.packs* to +correct this reading would be 12. ++ +The driver will attempt to detect this number automatically, but if +this fails somehow, you may want to override this value. ++ +Note that this is primarily useful for "guesstimation" of `battery.charge` +and/or `battery.runtime` (with `runtimecal` setting), if those readings are +not provided by the device directly. + +*battery_voltage_reports_one_pack*:: +Some devices "natively" report just report a part of the total battery voltage +(see also *override.battery.packs* above, if that value is not reported by the +device or properly guessed by the driver otherwise). ++ +If this flag is set, most of the subdrivers (except those which know about +more complicated device-specific nuances, currently: *ablerex*, *masterguard* +and *voltronic-qs-hex*) adjust their ultimately reported *battery.voltage* +value as a multiple of *battery.packs* and "native" *battery.voltage*). ++ +Note this is primarily useful for consistent diagnostics and graphing of the +numbers, and should not impact the "guesstimation" of `battery.charge` and/or +`battery.runtime` - so rather a cosmetic adjustment, than critical. *runtimecal =* 'value,value,value,value':: Parameter used in the (optional) runtime estimation. diff --git a/docs/nut.dict b/docs/nut.dict index e61a0605cd..9e6bf8a831 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3059 utf-8 +personal_ws-1.1 en 3062 utf-8 AAS ABI ACFAIL @@ -1935,6 +1935,7 @@ gtk guardpend guardpstart guesstimate +guesstimation guez gufw gui diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index cc085c2dc8..7782a1fc05 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -221,6 +221,39 @@ static struct { } load = { 0, 0.1, 1 }; static time_t battery_lastpoll = 0; +static int battery_voltage_reports_one_pack = 0, battery_voltage_reports_one_pack_considered = 0; + +/* Optionally multiply device-provided "battery.voltage" reading by + * the "battery.packs" (reading or common override setting) to end up + * with the dstate value representing the voltage of battery assembly, + * not that of a single cell/pack (different devices report different + * physically meaningful values for that reading). + * This shared method can be referenced from subdriver mapping tables. + */ +int multiply_battvolt(item_t *item, char *value, const size_t valuelen) { + float s; + + /* Adjusted here or not, this method was called at all + * and other code should not multiply again! */ + battery_voltage_reports_one_pack_considered = 1; + if (!battery_voltage_reports_one_pack || batt.packs < 2) { + /* (We assume by default that) this device already reports + * the sum-total voltage for the battery assembly - so just + * pass it on unmodified. + * Or we can't reasonably use a "batt.packs" anyway. + */ + snprintf(value, valuelen, "%s", item->value); + return 0; + } + + if (sscanf(item->value, "%f", &s) != 1) { + upsdebugx(2, "unparsable ss.ss %s", item->value); + return -1; + } + + snprintf(value, valuelen, "%.2f", s * batt.packs); + return 0; +} /* Fill batt.volt.act and guesstimate the battery charge * if it isn't already available. */ @@ -233,7 +266,10 @@ static int qx_battery(void) return -1; } - batt.volt.act = batt.packs * strtod(val, NULL); + batt.volt.act = strtod(val, NULL); + if (!battery_voltage_reports_one_pack_considered) { + batt.volt.act *= batt.packs; + } if (d_equal(batt.chrg.act, -1) && batt.volt.low > 0 && batt.volt.high > batt.volt.low) { @@ -323,6 +359,11 @@ static void qx_initbattery(void) batt_packs_known = 1; } + val = dstate_getinfo("battery_voltage_reports_one_pack"); + if (val) { + battery_voltage_reports_one_pack = 1; + } + /* Guesstimation: init values if not provided by device/overrides */ if (!dstate_getinfo("battery.charge") || !dstate_getinfo("battery.runtime")) { @@ -2674,6 +2715,11 @@ void upsdrv_makevartable(void) addvar(VAR_VALUE, "idleload", "Minimum load to be used for runtime calculation"); + addvar(VAR_FLAG, "battery_voltage_reports_one_pack", + "If your device natively reports battery.voltage of a single cell/pack, " + "multiply that into voltage of the whole battery assembly. " + "You may need an override.battery.packs=N setting also."); + #ifdef QX_USB addvar(VAR_VALUE, "subdriver", "Serial-over-USB subdriver selection"); /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ @@ -3781,7 +3827,10 @@ static bool_t qx_ups_walk(walkmode_t mode) * https://github.com/networkupstools/nut/pull/1027 */ - batt.volt.act = batt.packs * strtod(val, NULL); + batt.volt.act = strtod(val, NULL); + if (!battery_voltage_reports_one_pack_considered) { + batt.volt.act *= batt.packs; + } if (batt.volt.act > 0 && batt.volt.low > 0 && batt.volt.high > batt.volt.low) { diff --git a/drivers/nutdrv_qx.h b/drivers/nutdrv_qx.h index 0fc18e425d..a84907d337 100644 --- a/drivers/nutdrv_qx.h +++ b/drivers/nutdrv_qx.h @@ -179,6 +179,9 @@ unsigned int qx_status(void); /* Edit the current status: it takes one of the NUT status (all but OB are supported, simply set it as not OL), eventually preceded with an exclamation mark to clear it from the status (e.g. !OL). */ void update_status(const char *nutvalue); + /* Let subdrivers reference this: for devices that report "battery.voltage" of a single cell/pack, optionally multiply that into representing the whole assembly */ +int multiply_battvolt(item_t *item, char *value, const size_t valuelen); + /* Data for processing status values */ #define STATUS(x) ((unsigned int)1U< Date: Mon, 19 Sep 2022 19:10:15 +0200 Subject: [PATCH 0152/1232] drivers/nutdrv_qx.c: qx_initbattery(): extend default batt.volt.high range [#1279] --- drivers/nutdrv_qx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 7782a1fc05..86f91fa497 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -342,7 +342,12 @@ static void qx_initbattery(void) /* Basic formula, which should cover most cases */ batt.volt.low = 104 * batt.volt.nom / 120; - batt.volt.high = 130 * batt.volt.nom / 120; + /* Per https://www.csb-battery.com.tw/english/01_product/02_detail.php?fid=17&pid=113 + * a nominally 12V battery can have "float charging voltage" + * at 13.5-13.8V and an "equalization charging voltage" (e.g. + * to desulphurize) at 14-15V: + */ + batt.volt.high = 150 * batt.volt.nom / 120; /* Publish these data too */ dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low); From 27e3ffee3d938794f3e0a26b46261c4aff20f97b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 19:10:38 +0200 Subject: [PATCH 0153/1232] drivers/nutdrv_qx.c: qx_initbattery(): report if we autodetected number of battery packs [#1279] --- drivers/nutdrv_qx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 86f91fa497..e31d72b91d 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -398,6 +398,9 @@ static void qx_initbattery(void) } batt.packs = packs[i]; + upslogx(LOG_INFO, + "Autodetected %.0f as number of battery packs [%.0f/%.2f]", + batt.packs, batt.volt.nom, batt.volt.act); break; } From e9a196fb2ebe2d4bfe4d90e14bcc6e33c58c8793 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 19:12:06 +0200 Subject: [PATCH 0154/1232] drivers/blazer.c: blazer_packs(): extend default batt.volt.high range when guessing battery.packs count [#1279] --- drivers/blazer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/blazer.c b/drivers/blazer.c index adc1aa2a6f..97db12ad2a 100644 --- a/drivers/blazer.c +++ b/drivers/blazer.c @@ -150,7 +150,7 @@ static double blazer_packs(const char *ptr, char **endptr) for (i = 0; packs[i] > 0; i++) { - if (packs[i] * batt.volt.act > 1.2 * batt.volt.nom) { + if (packs[i] * batt.volt.act > 1.25 * batt.volt.nom) { continue; } From 56befa1707c0c195cec70d471c056c4512faabd9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 19:12:21 +0200 Subject: [PATCH 0155/1232] drivers/nutdrv_qx.c: qx_initbattery(): extend default batt.volt.high range when guessing battery.packs count [#1279] --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index e31d72b91d..c4a592512a 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -386,7 +386,7 @@ static void qx_initbattery(void) * therefore choose the one with the highest multiplier. */ for (i = 0; packs[i] > 0; i++) { - if (packs[i] * batt.volt.act > 1.2 * batt.volt.nom) { + if (packs[i] * batt.volt.act > 1.25 * batt.volt.nom) { continue; } From 65448a96683de708ba7c651b66ea90eae7cb2bfb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 19:16:14 +0200 Subject: [PATCH 0156/1232] drivers/blazer_{usb,ser}.c: bump DRIVER_VERSION due to changes in blazer.c [#1279] --- drivers/blazer_ser.c | 2 +- drivers/blazer_usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/blazer_ser.c b/drivers/blazer_ser.c index 6d82bbfce7..0986ab32e2 100644 --- a/drivers/blazer_ser.c +++ b/drivers/blazer_ser.c @@ -31,7 +31,7 @@ #include "blazer.h" #define DRIVER_NAME "Megatec/Q1 protocol serial driver" -#define DRIVER_VERSION "1.58" +#define DRIVER_VERSION "1.59" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 14ff1620d9..2bde209ff7 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -37,7 +37,7 @@ #endif #define DRIVER_NAME "Megatec/Q1 protocol USB driver" -#define DRIVER_VERSION "0.14" +#define DRIVER_VERSION "0.15" /* driver description structure */ upsdrv_info_t upsdrv_info = { From e2a041c2c700d9c27c165dd0b0762e53fc37a765 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 19 Sep 2022 19:15:35 +0200 Subject: [PATCH 0157/1232] NEWS: reflect extended default ranges for max battery voltage when guessing [#1279] --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 331b216be2..1cd85e4fd6 100644 --- a/NEWS +++ b/NEWS @@ -80,6 +80,9 @@ https://github.com/networkupstools/nut/milestone/8 * the `voltronic_qs_protocol` should now accept both "V" (as before) and newly "H" dialects, which otherwise seem interchangeable [#1623] + - nutdrv_qx and blazer updates: + * extended default ranges for max battery voltage when guessing [#1279] + - usbhid-ups updates: * cps-hid subdriver now applies same report descriptor fixing logic to devices with ProductID 0x0601 as done earlier for 0x0501, to get the From 8c768471f6822cd3d737651e2fb7e1bed19c5d8b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 21 Sep 2022 20:04:53 +0200 Subject: [PATCH 0158/1232] drivers/nutdrv_qx*: rename multiply_battvolt() to qx_multiply_battvolt() to remain specific about the code source --- drivers/nutdrv_qx.c | 2 +- drivers/nutdrv_qx.h | 2 +- drivers/nutdrv_qx_bestups.c | 2 +- drivers/nutdrv_qx_hunnox.c | 2 +- drivers/nutdrv_qx_mecer.c | 2 +- drivers/nutdrv_qx_megatec-old.c | 2 +- drivers/nutdrv_qx_megatec.c | 2 +- drivers/nutdrv_qx_mustek.c | 2 +- drivers/nutdrv_qx_q1.c | 2 +- drivers/nutdrv_qx_voltronic-qs.c | 2 +- drivers/nutdrv_qx_voltronic.c | 2 +- drivers/nutdrv_qx_zinto.c | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index c4a592512a..484083b2d9 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -230,7 +230,7 @@ static int battery_voltage_reports_one_pack = 0, battery_voltage_reports_one_pac * physically meaningful values for that reading). * This shared method can be referenced from subdriver mapping tables. */ -int multiply_battvolt(item_t *item, char *value, const size_t valuelen) { +int qx_multiply_battvolt(item_t *item, char *value, const size_t valuelen) { float s; /* Adjusted here or not, this method was called at all diff --git a/drivers/nutdrv_qx.h b/drivers/nutdrv_qx.h index a84907d337..0c5f20688a 100644 --- a/drivers/nutdrv_qx.h +++ b/drivers/nutdrv_qx.h @@ -180,7 +180,7 @@ unsigned int qx_status(void); void update_status(const char *nutvalue); /* Let subdrivers reference this: for devices that report "battery.voltage" of a single cell/pack, optionally multiply that into representing the whole assembly */ -int multiply_battvolt(item_t *item, char *value, const size_t valuelen); +int qx_multiply_battvolt(item_t *item, char *value, const size_t valuelen); /* Data for processing status values */ #define STATUS(x) ((unsigned int)1U< Date: Thu, 22 Sep 2022 12:31:10 +0200 Subject: [PATCH 0159/1232] drivers/nutdrv_qx.c: fix getval("battery_voltage_reports_one_pack") for the driver option flag [#1279] --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 484083b2d9..c6a719a2b4 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -364,7 +364,7 @@ static void qx_initbattery(void) batt_packs_known = 1; } - val = dstate_getinfo("battery_voltage_reports_one_pack"); + val = getval("battery_voltage_reports_one_pack"); if (val) { battery_voltage_reports_one_pack = 1; } From 64ca5a92590d8d61ba618f0296e223bfac4da329 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Sep 2022 13:02:51 +0200 Subject: [PATCH 0160/1232] drivers/nutdrv_qx.c: qx_multiply_battvolt(): init temporary "s" to 0 (so if sscanf() somehow fails/skips, we have a non-toxic outcome) --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index c6a719a2b4..e331066876 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -231,7 +231,7 @@ static int battery_voltage_reports_one_pack = 0, battery_voltage_reports_one_pac * This shared method can be referenced from subdriver mapping tables. */ int qx_multiply_battvolt(item_t *item, char *value, const size_t valuelen) { - float s; + float s = 0; /* Adjusted here or not, this method was called at all * and other code should not multiply again! */ From 9d33938358cf12f52427ee6a27c511952003a0a4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Sep 2022 12:45:03 +0200 Subject: [PATCH 0161/1232] drivers/nutdrv_qx.c: qx_initbattery(): adjust initially known "battery.voltage" right away, if we know the batt.packs and that battery_voltage_reports_one_pack [#1279] --- drivers/nutdrv_qx.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index e331066876..152d749c94 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -367,6 +367,28 @@ static void qx_initbattery(void) val = getval("battery_voltage_reports_one_pack"); if (val) { battery_voltage_reports_one_pack = 1; + /* If we already have a battery.voltage reading from the device, + * it is not yet "adjusted" to consider the multiplication for + * packs (if known; if not - the guesswork and call below for + * qx_battery() should take care of it). Note that it is only + * a few lines above that we might have learned the user-set + * amount of battery packs and that they know the device only + * reports a single pack voltage in the protocol. + * Even if the qx_multiply_battvolt() method was called before + * and set the battery_voltage_reports_one_pack_considered flag, + * it is not too relevant until now *for maths*. However it is + * important to know that the mapping table for this subdriver + * does reference the adjustment method at all (which it would + * encounter and set the flag while querying battery.voltage + * from device and having a non-NULL reading now). + */ + if (battery_voltage_reports_one_pack_considered) { + val = dstate_getinfo("battery.voltage"); + if (val && batt_packs_known && batt.packs > 1) { + batt.volt.act = strtod(val, NULL) * batt.packs; + dstate_setinfo("battery.voltage", "%.2f", batt.volt.act); + } + } } /* Guesstimation: init values if not provided by device/overrides */ From 9fb8d6d5f3baf27b15027126b8f9c782c155df35 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 8 Dec 2022 09:05:25 +0100 Subject: [PATCH 0162/1232] docs/nut.dict: update dict --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index e61a0605cd..2cfa367b89 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3059 utf-8 +personal_ws-1.1 en 3061 utf-8 AAS ABI ACFAIL @@ -744,7 +744,9 @@ NOTIFYMSG NQA NTP NUT's +NUTClient NUTSRC +NUTServer NVA NX Nadav From e5a54671b95ef0a3442c6307b54aed1dcdbf772f Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Tue, 20 Dec 2022 11:13:59 +0100 Subject: [PATCH 0163/1232] Fix discovery issue with Eaton pdu nlogic --- drivers/eaton-pdu-nlogic-mib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/eaton-pdu-nlogic-mib.c b/drivers/eaton-pdu-nlogic-mib.c index cebb869529..e1162e32d1 100644 --- a/drivers/eaton-pdu-nlogic-mib.c +++ b/drivers/eaton-pdu-nlogic-mib.c @@ -101,9 +101,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { ".1.3.6.1.4.1.534.7.1.1.2.1.4.1", "EATON", SU_FLAG_STATIC, NULL }, /* pduModel.1 = STRING: "200-240V, 24A, 5.0kVA, 50/60Hz" */ - /* Prefer ".1.3.6.1.2.1.1.1.0" / device.description */ { "device.model", ST_FLAG_STRING, SU_INFOSIZE, - ".1.3.6.1.2.1.1.1.0", /*".1.3.6.1.4.1.534.7.1.1.2.1.3.1", */ + ".1.3.6.1.4.1.534.7.1.1.2.1.3.1", "Eaton ePDU", SU_FLAG_STATIC, NULL }, /* pduSerialNumber.1 = STRING: "WMEL0046" */ { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, From fd7eff83b5d816100c07306a1d7f2cdc5e655dcc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 21 Dec 2022 21:47:08 +0100 Subject: [PATCH 0164/1232] tools/nut-usbinfo.pl: dumb syntax down for perl 5.005 (Solaris 8 compat) [#1736] --- tools/nut-usbinfo.pl | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index 17fc918bf6..ce528d394f 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -5,8 +5,9 @@ # Copyright (C) 2013 - 2014 Charles Lepple # Copyright (C) 2014 - 2022 Jim Klimov # -# Based on the usbdevice.pl script, made for the Ubuntu Media Center +# Based on the usbdevice.pl script, made for the Ubuntu Media Center # for the final use of the LIRC project. +# Syntax dumbed down a notch to support old perl interpreters. # # 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 @@ -90,7 +91,8 @@ sub gen_usb_files { # Hotplug file header - open my $outHotplug, ">$outputHotplug" || die "error $outputHotplug : $!"; + my $outHotplug = do {local *OUT_HOTPLUG}; + open $outHotplug, ">$outputHotplug" || die "error $outputHotplug : $!"; print $outHotplug '# This file is generated and installed by the Network UPS Tools package.'."\n"; print $outHotplug "#\n"; print $outHotplug '# Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID respectively) :'."\n"; @@ -102,7 +104,8 @@ sub gen_usb_files print $outHotplug ' bInterfaceProtocol driver_info'."\n"; # Udev file header - open my $outUdev, ">$outputUdev" || die "error $outputUdev : $!"; + my $outUdev = do {local *OUT_UDEV}; + open $outUdev, ">$outputUdev" || die "error $outputUdev : $!"; print $outUdev '# This file is generated and installed by the Network UPS Tools package.'."\n\n"; print $outUdev 'ACTION=="remove", GOTO="nut-usbups_rules_end"'."\n"; print $outUdev 'SUBSYSTEM=="usb_device", GOTO="nut-usbups_rules_real"'."\n"; @@ -110,12 +113,14 @@ sub gen_usb_files print $outUdev 'GOTO="nut-usbups_rules_end"'."\n\n"; print $outUdev 'LABEL="nut-usbups_rules_real"'."\n"; - open my $out_devd, ">$output_devd" || die "error $output_devd : $!"; + my $out_devd = do {local *OUT_DEVD}; + open $out_devd, ">$output_devd" || die "error $output_devd : $!"; print $out_devd '# This file is generated and installed by the Network UPS Tools package.'."\n"; print $out_devd "# Homepage: http://www.networkupstools.org/\n\n"; # UPower file header - open my $outputUPower, ">$outputUPower" || die "error $outputUPower : $!"; + my $outputUPower = do {local *OUT_UPOWER}; + open $outputUPower, ">$outputUPower" || die "error $outputUPower : $!"; print $outputUPower '##############################################################################################################'."\n"; print $outputUPower '# Uninterruptible Power Supplies with USB HID interfaces'."\n#\n"; print $outputUPower '# This file was automatically generated by NUT:'."\n"; @@ -125,7 +130,8 @@ sub gen_usb_files print $outputUPower "# or checkout the NUT repository and call 'tools/nut-usbinfo.pl'\n"; # Device scanner header - open my $outputDevScanner, ">$outputDevScanner" || die "error $outputDevScanner : $!"; + my $outputDevScanner = do {local *OUT_DEV_SCANNER}; + open $outputDevScanner, ">$outputDevScanner" || die "error $outputDevScanner : $!"; print $outputDevScanner '/* nutscan-usb'.$GPL_header."\n */\n\n"; print $outputDevScanner "#ifndef DEVSCAN_USB_H\n#define DEVSCAN_USB_H\n\n"; print $outputDevScanner "#include \"nut_stdint.h\"\t/* for uint16_t etc. */\n\n"; @@ -243,8 +249,9 @@ sub find_usbdevs my $nameFile=$_; my $lastComment=""; - open my $file,$nameFile or die "error open file $nameFile"; - while(my $line=<$file>) + my $file = do {local *FILE}; + open ($file, $nameFile) or die "error open file $nameFile"; + while(my $line = <$file>) { # catch comment (should permit comment on the precedent or on the current line of USB_DEVICE declaration) if($line =~/\s*\/\*(.+)\*\/\s*$/) @@ -262,10 +269,11 @@ sub find_usbdevs # Format: # /* vendor name */ # #define VENDORID 0x???? + my $fh = do {local *FH}; if(!($VendorID=~/\dx(\d|\w)+/)) { - open my $fh,$nameFile or die "error open file $nameFile"; - while(my $data=<$fh>) + open $fh, $nameFile or die "error open file $nameFile"; + while(my $data = <$fh>) { # catch Vendor Name if($data =~/\s*\/\*(.+)\*\/\s*$/) @@ -279,11 +287,13 @@ sub find_usbdevs last; } } + + close $fh; } # same thing for the productID if(!($ProductID=~/\dx(\d|\w)+/)) { - my $data = do { open my $fh, $nameFile or die "error open file $nameFile"; join '', <$fh> }; + my $data = do { open $fh, $nameFile or die "error open file $nameFile"; join '', <$fh> }; if ($data =~ /(#define|#DEFINE)\s+$ProductID\s+(\dx(\d|\w)+)/) { $ProductID=$2; From d4b0f7c3923a76c0442c4a40994df0d32bc74326 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 21 Dec 2022 21:58:38 +0100 Subject: [PATCH 0165/1232] autogen.sh: dumb syntax down for xpg/ksh88 or older [#1736] --- autogen.sh | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/autogen.sh b/autogen.sh index b3a24e3923..43018b66b2 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,6 +2,7 @@ # # Autoreconf wrapper script to ensure that the source tree is # in a buildable state +# NOTE: uses cumbersome dumbest-possible shell syntax for extra portability if [ -n "${PYTHON-}" ] ; then # May be a name/path of binary, or one with args - check both @@ -83,20 +84,23 @@ then fi fi -if [ ! -e scripts/systemd/nut-common.tmpfiles.in ]; then +if [ ! -f scripts/systemd/nut-common.tmpfiles.in ]; then echo '# autoconf requires this file exists before generating configure script; it will be overwritten by configure during a build' > scripts/systemd/nut-common.tmpfiles.in fi # now we can safely call autoreconf -if ( command -v dos2unix ) 2>/dev/null >/dev/null \ -&& ! ( dos2unix < configure.ac | cmp - configure.ac ) 2>/dev/null >/dev/null ; then - echo "WARNING: Did not confirm that configure.ac has Unix EOL markers;" - echo "this may cause issues for m4 parsing with autotools below." - if [ -e .git ] ; then - echo "You may want to enforce that Git uses 'lf' line endings and re-checkout:" - echo " :; git config core.autocrlf false && git config core.eol lf && rm .git/index && git checkout -f" +if ( command -v dos2unix ) 2>/dev/null >/dev/null ; then + if ( dos2unix < configure.ac | cmp - configure.ac ) 2>/dev/null >/dev/null ; then + : + else + echo "WARNING: Did not confirm that configure.ac has Unix EOL markers;" + echo "this may cause issues for m4 parsing with autotools below." + if [ -f .git ] || [ -d .git ] ; then + echo "You may want to enforce that Git uses 'lf' line endings and re-checkout:" + echo " :; git config core.autocrlf false && git config core.eol lf && rm .git/index && git checkout -f" + fi + echo "" fi - echo "" fi >&2 # Note: on some systems "autoreconf", "automake" et al are dispatcher From 8b613e6fb2008e9b019aadcecb2737a133b9ad09 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 21 Dec 2022 22:19:30 +0100 Subject: [PATCH 0166/1232] autogen.sh: enhance report of failed syntax checks [#1736] --- autogen.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index 43018b66b2..dbd00cbd26 100755 --- a/autogen.sh +++ b/autogen.sh @@ -110,5 +110,9 @@ fi >&2 echo "Calling autoreconf..." autoreconf -iv && { sh -n configure 2>/dev/null >/dev/null \ - || { echo "FAILED: configure script did not pass shell interpreter syntax checks" >&2 ; exit 1; } + || { echo "FAILED: configure script did not pass shell interpreter syntax checks" >&2 ; + head -1 configure + echo "NOTE: If you are using an older OS release, try executing the script with" >&2 + echo "a more functional shell implementation (dtksh, bash, dash...)" >&2 + exit 1; } } From 002aeeedb62b934caaee6dea23f2aca62c80e1f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 11:35:06 +0100 Subject: [PATCH 0167/1232] autogen.sh: support CONFIG_SHELL envvar to embed into generated configure script (and syntax-check with it) [#1736] --- autogen.sh | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/autogen.sh b/autogen.sh index dbd00cbd26..391c70a0ee 100755 --- a/autogen.sh +++ b/autogen.sh @@ -103,16 +103,50 @@ if ( command -v dos2unix ) 2>/dev/null >/dev/null ; then fi fi >&2 +echo "Calling autoreconf..." +autoreconf -iv && [ -s configure ] && [ -x configure ] \ +|| { cat << EOF +FAILED: did not generate an executable configure script! + # Note: on some systems "autoreconf", "automake" et al are dispatcher # scripts, and need you to explicitly say which version you want, e.g. # export AUTOCONF_VERSION=2.65 AUTOMAKE_VERSION=1.10 # If you get issues with AC_DISABLE_STATIC make sure you have libtool. -echo "Calling autoreconf..." -autoreconf -iv && { - sh -n configure 2>/dev/null >/dev/null \ - || { echo "FAILED: configure script did not pass shell interpreter syntax checks" >&2 ; - head -1 configure - echo "NOTE: If you are using an older OS release, try executing the script with" >&2 - echo "a more functional shell implementation (dtksh, bash, dash...)" >&2 - exit 1; } +EOF + exit 1 +} >&2 + +# Some autoconf versions may leave "/bin/sh" regardless of CONFIG_SHELL +# which originally was made for "recheck" operations +if [ -n "${CONFIG_SHELL-}" ]; then + case "${CONFIG_SHELL-}" in + */*) ;; # use as is, assume full path + *) + ENV_PROG="`command -v env`" 2>/dev/null + if [ -n "$ENV_PROG" -a -x "$ENV_PROG" ] ; then + echo "Using '$ENV_PROG' to call unqualified CONFIG_SHELL program name '$CONFIG_SHELL'" >&2 + CONFIG_SHELL="$ENV_PROG $CONFIG_SHELL" + fi + ;; + esac + + echo "Injecting caller-provided CONFIG_SHELL='$CONFIG_SHELL' into the script" >&2 + echo "#!${CONFIG_SHELL}" > configure.tmp + cat configure >> configure.tmp + # keep the original file rights intact + cat configure.tmp > configure + rm configure.tmp +else + CONFIG_SHELL="`head -1 configure | sed 's,^#!,,'`" +fi + +# NOTE: Unquoted, may be multi-token +$CONFIG_SHELL -n configure 2>/dev/null >/dev/null \ +|| { echo "FAILED: configure script did not pass shell interpreter syntax checks with $CONFIG_SHELL" >&2 ; + echo "NOTE: If you are using an older OS release, try executing the script with" >&2 + echo "a more functional shell implementation (dtksh, bash, dash...)" >&2 + echo "You can re-run this script with a CONFIG_SHELL in environment" >&2 + exit 1 } + +echo "The generated configure script passed shell interpreter syntax checks" From 92d967eddf3520935ac71ccac4a3ecb63210b807 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 12:01:26 +0100 Subject: [PATCH 0168/1232] NEWS: autogen.sh support for CONFIG_SHELL [#1736] --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 506a175623..922ea37e8e 100644 --- a/NEWS +++ b/NEWS @@ -169,6 +169,10 @@ https://github.com/networkupstools/nut/milestone/8 - some fixes applied to Solaris/illumos packaging and SMF service support [#1554, #1564] + - some fixes for builds on older OSes with less functional default system + shell interpreters - now `autogen.sh` supports a `CONFIG_SHELL` envvar + to inject its value into generated `configure` script [#1736] + - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] From 39e0b7bd586d3e931f4c19a9380c5834664b5e81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 12:44:45 +0100 Subject: [PATCH 0169/1232] common/common.c: fix pragmas for systems without a UINTPTR_MAX defined [#1736] --- common/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index c8f931ab47..3eb3571345 100644 --- a/common/common.c +++ b/common/common.c @@ -49,7 +49,7 @@ const char *UPS_VERSION = NUT_VERSION_MACRO; /* Know which bitness we were built for, * to adjust the search paths for get_libname() */ #include "nut_stdint.h" -#if UINTPTR_MAX == 0xffffffffffffffffULL +#if defined(UINTPTR_MAX) && (UINTPTR_MAX + 0) == 0xffffffffffffffffULL # define BUILD_64 1 #else # ifdef BUILD_64 From 93f37ba8e91da3949366adfc1fc247066c56217a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:01:07 +0100 Subject: [PATCH 0170/1232] configure.ac, common/strnlen.c: Detect and provide a fallback strnlen() if needed [#1736] --- common/Makefile.am | 8 ++++++++ common/strnlen.c | 43 +++++++++++++++++++++++++++++++++++++++++++ configure.ac | 20 ++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 common/strnlen.c diff --git a/common/Makefile.am b/common/Makefile.am index eb7fe53d4b..9e64f050d1 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -46,6 +46,14 @@ libcommon_la_SOURCES += strptime.c libcommonclient_la_SOURCES += strptime.c endif +if HAVE_STRNLEN +EXTRA_DIST += strnlen.c +else +# fall back to FreeBSD implem +libcommon_la_SOURCES += strnlen.c +libcommonclient_la_SOURCES += strnlen.c +endif + if HAVE_STRSEP EXTRA_DIST += strsep.c else diff --git a/common/strnlen.c b/common/strnlen.c new file mode 100644 index 0000000000..94df9ffeaa --- /dev/null +++ b/common/strnlen.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2009 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/lib/libc/string/strnlen.c,v 1.1 2009/02/28 06:00:58 das Exp $"); + +#include + +size_t +strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} + diff --git a/configure.ac b/configure.ac index 4ee8734e36..b175a48d54 100644 --- a/configure.ac +++ b/configure.ac @@ -465,6 +465,26 @@ AS_IF([test x"${ac_cv_func_strptime}" = xyes], ) AM_CONDITIONAL([HAVE_STRPTIME], [test x"${ac_cv_func_strptime}" = "xyes"]) +AC_CACHE_CHECK([for strnlen(s1,s2,tm)], + [ac_cv_func_strnlen], + [AX_RUN_OR_LINK_IFELSE( + [AC_LANG_PROGRAM([$CODE_STRINGINCL +#include +], + [size_t len = strnlen("LongString", 5); +if (len != 5) return 5; + +len = strnlen("LongString", 50); +if (len != 10) return 10 +])], + [ac_cv_func_strnlen=yes], [ac_cv_func_strnlen=no] + )]) +AS_IF([test x"${ac_cv_func_strnlen}" = xyes], + [AC_DEFINE([HAVE_STRNLEN], 1, [defined if standard library has, and C standard allows, the strnlen(s1,s2) method])], + [AC_MSG_WARN([Optional C library routine strnlen not found; a fallback implementation will be built in])] + ) +AM_CONDITIONAL([HAVE_STRNLEN], [test x"${ac_cv_func_strnlen}" = "xyes"]) + AC_CACHE_CHECK([for strdup(s)], [ac_cv_func_strdup], [AX_RUN_OR_LINK_IFELSE( From cc6a523e6743069b3f95af04e632064b8318e1bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:04:31 +0100 Subject: [PATCH 0171/1232] common/strnlen.c: untie from freeBSD specifics [#1736] --- common/strnlen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/strnlen.c b/common/strnlen.c index 94df9ffeaa..1ad0340b4a 100644 --- a/common/strnlen.c +++ b/common/strnlen.c @@ -24,9 +24,12 @@ * SUCH DAMAGE. */ +/* // Includes amended for NUT cross-platform purposes #include __FBSDID("$FreeBSD: src/lib/libc/string/strnlen.c,v 1.1 2009/02/28 06:00:58 das Exp $"); +*/ +#include #include size_t From 371d1dc53f4756ce487f7a009006332cfd0aa54b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:11:04 +0100 Subject: [PATCH 0172/1232] drivers/riello*.{c,h}: do not directly include stdint.h (not ubiquitous) [#1736] --- drivers/riello.c | 1 - drivers/riello.h | 2 +- drivers/riello_ser.c | 1 - drivers/riello_usb.c | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/riello.c b/drivers/riello.c index 29f3269456..48cc1cd1db 100644 --- a/drivers/riello.c +++ b/drivers/riello.c @@ -27,7 +27,6 @@ */ #include -#include #include "main.h" #include "riello.h" diff --git a/drivers/riello.h b/drivers/riello.h index 971c441672..a2ab948701 100644 --- a/drivers/riello.h +++ b/drivers/riello.h @@ -29,7 +29,7 @@ #ifndef NUT_RIELLO_H_SEEN #define NUT_RIELLO_H_SEEN 1 -#include +#include "nut_stdint.h" #define CTRL_RETRIES 50 #define CTRL_TIMEOUT 100 diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index 022f658fa6..72ef709ae0 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -27,7 +27,6 @@ #include "config.h" /* must be the first header */ #include -#include #ifdef WIN32 # include "wincompat.h" diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index cec64f5ae4..0dc257ddf9 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -28,8 +28,6 @@ #include "config.h" /* must be the first header */ -#include - #include "main.h" #include "nut_libusb.h" #include "usb-common.h" From f93dbfe537527f2b4ee60f1ad9f46feb3e4be42c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:16:11 +0100 Subject: [PATCH 0173/1232] common/strptime.c: do not always directly include stdint.h (not ubiquitous) [#1736] --- common/strptime.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/strptime.c b/common/strptime.c index 1672ded8ad..ab7a44aa4f 100644 --- a/common/strptime.c +++ b/common/strptime.c @@ -45,7 +45,11 @@ __RCSID("$NetBSD: strptime.c,v 1.36 2012/03/13 21:13:48 christos Exp $"); #include #include #include -#include +#if defined HAVE_STDINT_H +# include +#else +# include "nut_stdint.h" +#endif /* #include #include "private.h" From 8a5848c26bdfab856c56e8aead555edc2c95a3b5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:16:31 +0100 Subject: [PATCH 0174/1232] drivers/adelsystem_cbi.c: do not directly include stdint.h (not ubiquitous) [#1736] --- drivers/adelsystem_cbi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/adelsystem_cbi.h b/drivers/adelsystem_cbi.h index 1169d5e2c3..11fb938e2a 100644 --- a/drivers/adelsystem_cbi.h +++ b/drivers/adelsystem_cbi.h @@ -27,7 +27,7 @@ #ifndef ADELSYSTEM_CBI_H #define ADELSYSTEM_CBI_H -#include +#include "nut_stdint.h" /* UPS device details */ #define DEVICE_MFR "ADELSYSTEM" From a5cd69eaa5e01aa059175ca218124373a60c1259 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:16:56 +0100 Subject: [PATCH 0175/1232] drivers/eaton-pdu-marlin-helpers.c: do not directly include stdint.h (not ubiquitous) [#1736] --- drivers/eaton-pdu-marlin-helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/eaton-pdu-marlin-helpers.c b/drivers/eaton-pdu-marlin-helpers.c index 421045f4c8..ca1a625872 100644 --- a/drivers/eaton-pdu-marlin-helpers.c +++ b/drivers/eaton-pdu-marlin-helpers.c @@ -32,8 +32,8 @@ #include #include -#include +#include "nut_stdint.h" #include "eaton-pdu-marlin-helpers.h" #include "dstate.h" #include "common.h" From 1e04977013e5a259bfe5943bcf8d15816ce5c639 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:17:13 +0100 Subject: [PATCH 0176/1232] drivers/pijuice.c: do not directly include stdint.h (not ubiquitous) [#1736] --- drivers/pijuice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pijuice.c b/drivers/pijuice.c index a1b1db1845..1229984365 100644 --- a/drivers/pijuice.c +++ b/drivers/pijuice.c @@ -20,7 +20,7 @@ #include "main.h" #include -#include +#include "nut_stdint.h" /* * Linux I2C userland is a bit of a mess until distros refresh to From 6455b9d8378affd1813a5b2550bb749a7c7a86b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:17:28 +0100 Subject: [PATCH 0177/1232] tests/getvaluetest.c: do not directly include stdint.h (not ubiquitous) [#1736] --- tests/getvaluetest.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/getvaluetest.c b/tests/getvaluetest.c index 4945915da0..fdaffc1cae 100644 --- a/tests/getvaluetest.c +++ b/tests/getvaluetest.c @@ -29,8 +29,7 @@ #include "config.h" -#include -#include +#include "nut_stdint.h" #include #include #include From 24def442f32637638c3157a220b95771179d62fd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:24:43 +0100 Subject: [PATCH 0178/1232] drivers/mge-hid.c: provide a fallback round() [#1736] --- drivers/mge-hid.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 798e64fd28..93ffcba66b 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -186,6 +186,25 @@ static char mge_scratch_buf[20]; /* Internal flag to process battery status (CHRG/DISCHRG) and ABM */ static int advanced_battery_monitoring = ABM_UNKNOWN; +/* TODO: Lifted from strptime.c... maybe should externalize the fallback? */ +#ifndef HAVE_ROUND +# ifndef WIN32 +static long round (double value) +# else +static long round (LDOUBLE value) +# endif +{ + long intpart; + + intpart = (long)value; + value = value - intpart; + if (value >= 0.5) + intpart++; + + return intpart; +} +#endif /* HAVE_ROUND */ + /* Used to store internally if ABM is enabled or not */ static const char *eaton_abm_enabled_fun(double value) { From d7220b436f3f2975a3cc59b8f1d9982a3040fe34 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:33:05 +0100 Subject: [PATCH 0179/1232] scripts/augeas/Makefile.am: avoid spurious error messages when PYTHON=no [#1736] --- scripts/augeas/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/augeas/Makefile.am b/scripts/augeas/Makefile.am index b9b8c8e860..c24611d06d 100644 --- a/scripts/augeas/Makefile.am +++ b/scripts/augeas/Makefile.am @@ -9,7 +9,7 @@ PYTHON = @PYTHON@ # is assumed to only differ from a generated gen-nutupsconf-aug.py by the # @PYTHON@ shebang. dist-hook: - @if [ -n "$(PYTHON)" ] && $(PYTHON) -c "import re,glob,codecs"; then \ + @if [ -n "$(PYTHON)" ] && [ x"no" != x"$(PYTHON)" ] && $(PYTHON) -c "import re,glob,codecs"; then \ echo "Regenerating Augeas ups.conf lens with '$(PYTHON)'."; \ $(PYTHON) $(distdir)/gen-nutupsconf-aug.py.in $(distdir)/; \ else \ From 53987576515f2c706bc1738c3e4479ad7cafcfdb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:33:15 +0100 Subject: [PATCH 0180/1232] tools/Makefile.am: avoid spurious error messages when PYTHON=no [#1736] --- tools/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index 90951953b3..49af8d9153 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -48,7 +48,7 @@ nut-scanner-deps-usb: $(GENERATED_USB_FILES) # The distributed nut-snmpinfo.py.in template is assumed to only differ from # a generated nut-snmpinfo.py by the @PYTHON@ shebang. $(GENERATED_SNMP_FILES): $(top_srcdir)/drivers/*-mib.c - @if [ -n "$(PYTHON)" ] && $(PYTHON) -c 1; then \ + @if [ -n "$(PYTHON)" ] && [ x"no" != x"$(PYTHON)" ] && $(PYTHON) -c 1; then \ echo "Regenerating the SNMP helper files in SRC dir with '$(PYTHON)'."; \ TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ @@ -83,7 +83,7 @@ $(GENERATED_USB_FILES): $(top_srcdir)/drivers/*-hid.c $(top_srcdir)/drivers/*usb # The distributed nut-snmpinfo.py.in template is assumed to only differ from # a generated nut-snmpinfo.py by the @PYTHON@ shebang. dist-hook: - @if [ -n "$(PYTHON)" ] && $(PYTHON) -c 1; then \ + @if [ -n "$(PYTHON)" ] && [ x"no" != x"$(PYTHON)" ] && $(PYTHON) -c 1; then \ echo "Regenerating the SNMP helper files in DIST dir with '$(PYTHON)'."; \ TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ From 1105ea81785c6af3a6c7d173ebeb9a828e159c32 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:47:43 +0100 Subject: [PATCH 0181/1232] configure.ac, tools/nut-scanner/Makefile.am: if we HAVE_SEMAPHORE, some systems may need additional SEMLIBS [#1736] --- configure.ac | 9 +++++++++ tools/nut-scanner/Makefile.am | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/configure.ac b/configure.ac index b175a48d54..da664e30af 100644 --- a/configure.ac +++ b/configure.ac @@ -293,6 +293,7 @@ AC_CHECK_HEADER([poll.h], [AC_DEFINE([HAVE_POLL_H], [1], [Define to 1 if you have .])]) +SEMLIBS="" AC_CHECK_HEADER([semaphore.h], [AC_DEFINE([HAVE_SEMAPHORE_H], [1], [Define to 1 if you have .]) @@ -311,12 +312,19 @@ sem_destroy(&semaphore); [AC_DEFINE([HAVE_SEMAPHORE], [1], [Define to 1 if you have with usable sem_t sem_init() and sem_destroy().]) AC_MSG_RESULT([ok]) + + dnl Solaris 8 builds complain about indirect dependency involved: + dnl sem_init nut_scanner-nut-scanner.o + dnl (symbol belongs to implicit dependency /usr/lib/librt.so.1) + + AC_CHECK_LIB(rt, sem_init, SEMLIBS="-lrt") ], [AC_MSG_RESULT([no])] ) AC_LANG_POP([C]) ] ) +AM_CONDITIONAL(HAVE_SEMAPHORE_LIBS, test -n "${SEMLIBS}") AC_CHECK_FUNCS(cfsetispeed tcsendbreak) AC_CHECK_FUNCS(seteuid setsid getpassphrase) @@ -3236,6 +3244,7 @@ AC_SUBST(DRIVER_MAN_LIST_PAGES) AC_SUBST(DRIVER_INSTALL_TARGET) AC_SUBST(NETLIBS) AC_SUBST(SERLIBS) +AC_SUBST(SEMLIBS) AC_SUBST(PIDPATH) AC_SUBST(STATEPATH) AC_SUBST(ALTPIDPATH) diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 2fcd26c946..354b3f6f41 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -58,6 +58,10 @@ if WITH_LIBLTDL libnutscan_la_LIBADD += $(LIBLTDL_LIBS) endif libnutscan_la_LIBADD += $(top_builddir)/common/libcommonclient.la +if HAVE_SEMAPHORE_LIBS +# Are additional libraries needed for semaphore support? +libnutscan_la_LIBADD += $(SEMLIBS) +endif # FIXME: From old ages onward, SERLIBS are added here and not in LIBADD... why? libnutscan_la_LDFLAGS = $(SERLIBS) From 2648d37e0e722f48ce22f929345ffb5e07138256 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 13:53:58 +0100 Subject: [PATCH 0182/1232] tools/nut-usbinfo.pl: old typo fix (overlaid file variable and file name) --- tools/nut-usbinfo.pl | 94 ++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index ce528d394f..bba85ccf1c 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -119,50 +119,50 @@ sub gen_usb_files print $out_devd "# Homepage: http://www.networkupstools.org/\n\n"; # UPower file header - my $outputUPower = do {local *OUT_UPOWER}; - open $outputUPower, ">$outputUPower" || die "error $outputUPower : $!"; - print $outputUPower '##############################################################################################################'."\n"; - print $outputUPower '# Uninterruptible Power Supplies with USB HID interfaces'."\n#\n"; - print $outputUPower '# This file was automatically generated by NUT:'."\n"; - print $outputUPower '# https://github.com/networkupstools/nut/'."\n#\n"; - print $outputUPower '# To keep up to date, monitor upstream NUT'."\n"; - print $outputUPower '# https://github.com/networkupstools/nut/commits/master/scripts/upower/95-upower-hid.hwdb'."\n"; - print $outputUPower "# or checkout the NUT repository and call 'tools/nut-usbinfo.pl'\n"; + my $outUPower = do {local *OUT_UPOWER}; + open $outUPower, ">$outputUPower" || die "error $outputUPower : $!"; + print $outUPower '##############################################################################################################'."\n"; + print $outUPower '# Uninterruptible Power Supplies with USB HID interfaces'."\n#\n"; + print $outUPower '# This file was automatically generated by NUT:'."\n"; + print $outUPower '# https://github.com/networkupstools/nut/'."\n#\n"; + print $outUPower '# To keep up to date, monitor upstream NUT'."\n"; + print $outUPower '# https://github.com/networkupstools/nut/commits/master/scripts/upower/95-upower-hid.hwdb'."\n"; + print $outUPower "# or checkout the NUT repository and call 'tools/nut-usbinfo.pl'\n"; # Device scanner header - my $outputDevScanner = do {local *OUT_DEV_SCANNER}; - open $outputDevScanner, ">$outputDevScanner" || die "error $outputDevScanner : $!"; - print $outputDevScanner '/* nutscan-usb'.$GPL_header."\n */\n\n"; - print $outputDevScanner "#ifndef DEVSCAN_USB_H\n#define DEVSCAN_USB_H\n\n"; - print $outputDevScanner "#include \"nut_stdint.h\"\t/* for uint16_t etc. */\n\n"; - print $outputDevScanner "#include \t/* for PATH_MAX in usb.h etc. */\n\n"; - print $outputDevScanner "#include \t/* for MAXPATHLEN etc. */\n\n"; - print $outputDevScanner "/* libusb header file */\n"; - print $outputDevScanner "#if (!WITH_LIBUSB_1_0) && (!WITH_LIBUSB_0_1)\n"; - print $outputDevScanner "#error \"configure script error: Neither WITH_LIBUSB_1_0 nor WITH_LIBUSB_0_1 is set\"\n"; - print $outputDevScanner "#endif\n\n"; - print $outputDevScanner "#if (WITH_LIBUSB_1_0) && (WITH_LIBUSB_0_1)\n"; - print $outputDevScanner "#error \"configure script error: Both WITH_LIBUSB_1_0 and WITH_LIBUSB_0_1 are set\"\n"; - print $outputDevScanner "#endif\n\n"; - print $outputDevScanner "#if WITH_LIBUSB_1_0\n"; - print $outputDevScanner "# include \n"; - print $outputDevScanner "#endif\n"; - print $outputDevScanner "#if WITH_LIBUSB_0_1\n"; - print $outputDevScanner "# ifdef HAVE_USB_H\n"; - print $outputDevScanner "# include \n"; - print $outputDevScanner "# else\n"; - print $outputDevScanner "# ifdef HAVE_LUSB0_USB_H\n"; - print $outputDevScanner "# include \n"; - print $outputDevScanner "# else\n"; - print $outputDevScanner "# error \"configure script error: Neither HAVE_USB_H nor HAVE_LUSB0_USB_H is set for the WITH_LIBUSB_0_1 build\"\n"; - print $outputDevScanner "# endif\n"; - print $outputDevScanner "# endif\n"; - print $outputDevScanner " /* simple remap to avoid bloating structures */\n"; - print $outputDevScanner " typedef usb_dev_handle libusb_device_handle;\n"; - print $outputDevScanner "#endif\n"; + my $outDevScanner = do {local *OUT_DEV_SCANNER}; + open $outDevScanner, ">$outputDevScanner" || die "error $outputDevScanner : $!"; + print $outDevScanner '/* nutscan-usb'.$GPL_header."\n */\n\n"; + print $outDevScanner "#ifndef DEVSCAN_USB_H\n#define DEVSCAN_USB_H\n\n"; + print $outDevScanner "#include \"nut_stdint.h\"\t/* for uint16_t etc. */\n\n"; + print $outDevScanner "#include \t/* for PATH_MAX in usb.h etc. */\n\n"; + print $outDevScanner "#include \t/* for MAXPATHLEN etc. */\n\n"; + print $outDevScanner "/* libusb header file */\n"; + print $outDevScanner "#if (!WITH_LIBUSB_1_0) && (!WITH_LIBUSB_0_1)\n"; + print $outDevScanner "#error \"configure script error: Neither WITH_LIBUSB_1_0 nor WITH_LIBUSB_0_1 is set\"\n"; + print $outDevScanner "#endif\n\n"; + print $outDevScanner "#if (WITH_LIBUSB_1_0) && (WITH_LIBUSB_0_1)\n"; + print $outDevScanner "#error \"configure script error: Both WITH_LIBUSB_1_0 and WITH_LIBUSB_0_1 are set\"\n"; + print $outDevScanner "#endif\n\n"; + print $outDevScanner "#if WITH_LIBUSB_1_0\n"; + print $outDevScanner "# include \n"; + print $outDevScanner "#endif\n"; + print $outDevScanner "#if WITH_LIBUSB_0_1\n"; + print $outDevScanner "# ifdef HAVE_USB_H\n"; + print $outDevScanner "# include \n"; + print $outDevScanner "# else\n"; + print $outDevScanner "# ifdef HAVE_LUSB0_USB_H\n"; + print $outDevScanner "# include \n"; + print $outDevScanner "# else\n"; + print $outDevScanner "# error \"configure script error: Neither HAVE_USB_H nor HAVE_LUSB0_USB_H is set for the WITH_LIBUSB_0_1 build\"\n"; + print $outDevScanner "# endif\n"; + print $outDevScanner "# endif\n"; + print $outDevScanner " /* simple remap to avoid bloating structures */\n"; + print $outDevScanner " typedef usb_dev_handle libusb_device_handle;\n"; + print $outDevScanner "#endif\n"; # vid, pid, driver - print $outputDevScanner "typedef struct {\n\tuint16_t\tvendorID;\n\tuint16_t\tproductID;\n\tchar*\tdriver_name;\n} usb_device_id_t;\n\n"; - print $outputDevScanner "/* USB IDs device table */\nstatic usb_device_id_t usb_device_table[] = {\n\n"; + print $outDevScanner "typedef struct {\n\tuint16_t\tvendorID;\n\tuint16_t\tproductID;\n\tchar*\tdriver_name;\n} usb_device_id_t;\n\n"; + print $outDevScanner "/* USB IDs device table */\nstatic usb_device_id_t usb_device_table[] = {\n\n"; # generate the file in alphabetical order (first for VendorID, then for ProductID) foreach my $vendorId (sort { lc $a cmp lc $b } keys %vendorName) @@ -215,21 +215,21 @@ sub gen_usb_files { if (!$upowerVendorHasDevices) { if ($vendorName{$vendorId}) { - print $outputUPower "\n# ".$vendorName{$vendorId}."\n"; + print $outUPower "\n# ".$vendorName{$vendorId}."\n"; } $upowerVendorHasDevices = 1; } - print $outputUPower "usb:v".uc(removeHexPrefix($vendorId))."p".uc(removeHexPrefix($productId))."*\n"; + print $outUPower "usb:v".uc(removeHexPrefix($vendorId))."p".uc(removeHexPrefix($productId))."*\n"; } # Device scanner entry - print $outputDevScanner "\t{ ".$vendorId.', '.$productId.", \"".$vendor{$vendorId}{$productId}{"driver"}."\" },\n"; + print $outDevScanner "\t{ ".$vendorId.', '.$productId.", \"".$vendor{$vendorId}{$productId}{"driver"}."\" },\n"; } if ($upowerVendorHasDevices) { - print $outputUPower " UPOWER_BATTERY_TYPE=ups\n"; + print $outUPower " UPOWER_BATTERY_TYPE=ups\n"; if ($vendorName{$vendorId}) { - print $outputUPower " UPOWER_VENDOR=".$vendorName{$vendorId}."\n"; + print $outUPower " UPOWER_VENDOR=".$vendorName{$vendorId}."\n"; } } @@ -238,7 +238,7 @@ sub gen_usb_files print $outUdev "\n".'LABEL="nut-usbups_rules_end"'."\n"; # Device scanner footer - print $outputDevScanner "\n\t/* Terminating entry */\n\t{ 0, 0, NULL }\n};\n#endif /* DEVSCAN_USB_H */\n\n"; + print $outDevScanner "\n\t/* Terminating entry */\n\t{ 0, 0, NULL }\n};\n#endif /* DEVSCAN_USB_H */\n\n"; } sub find_usbdevs From 91808639112df051c277f411af6ce65020e17b22 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 14:18:24 +0100 Subject: [PATCH 0183/1232] tests/NIT/nit.sh: dumb down shell syntax for older Solaris interpreter [#1736] --- tests/NIT/nit.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0883f95369..d2c219636b 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -114,7 +114,7 @@ isBusy_NUT_PORT() { ( # Hide this looped noise: # ./nit.sh: connect: Connection refused # ./nit.sh: line 112: /dev/tcp/localhost/35050: Connection refused - if ! shouldDebug ; then + if shouldDebug ; then : ; else exec 2>/dev/null fi for H in "localhost" "127.0.0.1" "::1"; do @@ -176,7 +176,7 @@ case "${BUILDDIR}" in TOP_BUILDDIR="`cd "${BUILDDIR}"/../.. && pwd`" ;; *) log_info "Current directory '${BUILDDIR}' is not a .../tests/NIT" ;; esac -if ! test -w "${BUILDDIR}" ; then +if test ! -w "${BUILDDIR}" ; then log_error "BUILDDIR='${BUILDDIR}' is not writeable, tests may fail below" fi @@ -226,7 +226,9 @@ TESTDIR="$BUILDDIR/tmp" # we reserve 17 chars for "/dummy-ups-dummy" longest filename. if [ `echo "$TESTDIR" | wc -c` -gt 80 ]; then log_info "'$TESTDIR' is too long to store AF_UNIX socket files, will mktemp" - if ! ( [ -n "${TMPDIR-}" ] && [ -d "${TMPDIR-}" ] && [ -w "${TMPDIR-}" ] ) ; then + if ( [ -n "${TMPDIR-}" ] && [ -d "${TMPDIR-}" ] && [ -w "${TMPDIR-}" ] ) ; then + : + else if [ -d /dev/shm ] && [ -w /dev/shm ]; then TMPDIR=/dev/shm ; else TMPDIR=/tmp ; fi fi TESTDIR="`mktemp -d "${TMPDIR}/nit-tmp.$$.XXXXXX"`" || die "Failed to mktemp" @@ -278,7 +280,7 @@ else && [ "$NUT_PORT" -gt 0 ] && [ "$NUT_PORT" -lt 65536 ] \ || NUT_PORT=34931 - if ! isBusy_NUT_PORT ; then + if isBusy_NUT_PORT ; then : ; else break fi @@ -296,7 +298,7 @@ else && [ "$DELTA2" -ge 0 ] || die "Can not pick random port" NUT_PORT="`expr $DELTA1 + $DELTA2`" - if ! isBusy_NUT_PORT ; then + if isBusy_NUT_PORT ; then : ; else break fi @@ -604,7 +606,9 @@ testcase_upsd_allow_no_device() { log_separator log_info "Query listing from UPSD by UPSC (no devices configured yet) to test that UPSD responds to UPSC" - if ! runcmd upsc -l localhost:$NUT_PORT ; then + if runcmd upsc -l localhost:$NUT_PORT ; then + : + else # Note: avoid exact matching for stderr, because it can have Init SSL messages etc. if echo "$CMDERR" | grep "Error: Server disconnected" >/dev/null ; then log_warn "Retry once to rule out laggy systems" @@ -830,9 +834,8 @@ testcase_sandbox_start_drivers_after_upsd() { COUNTDOWN=60 # TODO: Convert to runcmd()? OUT="" - while [ x"$OUT" = x"ups.status: WAIT" ] \ - || ! OUT="`upsc $U@localhost:$NUT_PORT ups.status`" \ - ; do + while [ x"$OUT" = x"ups.status: WAIT" ] ; do + OUT="`upsc $U@localhost:$NUT_PORT ups.status`" || break [ x"$OUT" = x"ups.status: WAIT" ] || { log_info "Got output:"; echo "$OUT"; break; } sleep 1 COUNTDOWN="`expr $COUNTDOWN - 1`" @@ -1154,7 +1157,7 @@ fi # Allow to leave the sandbox daemons running for a while, # to experiment with them interactively: if [ -n "${DEBUG_SLEEP-}" ] ; then - if ! [ "${DEBUG_SLEEP-}" -gt 0 ] ; then + if [ "${DEBUG_SLEEP-}" -gt 0 ] ; then : ; else DEBUG_SLEEP=60 fi From cd488da768c9a03dba690f09884335ca27fa87e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 14:24:43 +0100 Subject: [PATCH 0184/1232] tests/NIT/nit.sh: avoid "sed -i" [#1736] --- tests/NIT/nit.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index d2c219636b..0288b3bd4d 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -506,8 +506,12 @@ EOF # HACK: Avoid empty ups.status that may be present in example docs # FIXME: Might we actually want that value (un-)set for tests?.. # TODO: Check if the problem was with dummy-ups looping? [#1385] + # Avoid "sed -i", it behaves differently on some platforms + # and is completely absent on others [#1736 and earlier] for F in "$NUT_CONFPATH/"*.dev "$NUT_CONFPATH/"*.seq ; do - sed -e 's,^ups.status: *$,ups.status: OL BOOST,' -i'.bak' "$F" + sed -e 's,^ups.status: *$,ups.status: OL BOOST,' < "$F" > "$F.bak" + cat "$F.bak" > "$F" + rm -f "$F.bak" grep -E '^ups.status:' "$F" >/dev/null || { echo "ups.status: OL BOOST" >> "$F"; } done fi From 0fb24fea0fd586de9c0a9a9d36ffd19f6dda91c4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 14:25:07 +0100 Subject: [PATCH 0185/1232] tests/NIT/nit.sh: avoid PYTHON=no [#1736] --- tests/NIT/nit.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0288b3bd4d..f589c781e4 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -917,6 +917,10 @@ isTestablePython() { ; then return 1 fi + PY_SHEBANG="`head -1 "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py"`" + if [ x"${PY_SHEBANG}" = x"#!no" ] ; then + return 1 + fi return 0 } From 4720a3afc2149c3c076581090f5b2e19e8097cfe Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 14:42:35 +0100 Subject: [PATCH 0186/1232] tests/nutlogtest.c: reword message so we see it even if libc printf("%s", NULL) does a null-dereference [#1736] --- tests/nutlogtest.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/nutlogtest.c b/tests/nutlogtest.c index 09342c76b4..5aaad31ea8 100644 --- a/tests/nutlogtest.c +++ b/tests/nutlogtest.c @@ -29,7 +29,9 @@ int main(void) { # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat-overflow" #endif - upsdebugx(0, "D: checking with libc handling of NULL: '%s' vs '%s'", s1, s2); + + upsdebugx(0, "D: checking with libc handling of NULL (can segfault for some libc implementations):"); + upsdebugx(0, "D: '%s' vs '%s'", s1, s2); /* This explicitly does not work with -Wformat, due to verbatim NULL without a var: * nutlogtest.c:20:5: error: reading through null pointer (argument 4) [-Werror=format=] From ce9864708f8ce494c690ad8e026be1916c38b08c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 15:22:17 +0100 Subject: [PATCH 0187/1232] configure.ac, tests/Makefile.am: introduce and check for REQUIRE_NUT_STRARG flag [#1736, #1737] --- configure.ac | 23 +++++++++++++++++++++++ tests/.gitignore | 1 + tests/Makefile.am | 21 ++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index da664e30af..1806b9dae9 100644 --- a/configure.ac +++ b/configure.ac @@ -613,6 +613,29 @@ AC_CHECK_FUNCS(vsnprintf snprintf, [], [ AC_TYPE_LONG_LONG_INT ]) +AC_MSG_CHECKING([whether printf allows null string args]) +AC_LANG_PUSH([C]) +dnl The following code crashes on some libc implementations (e.g. Solaris 8) +dnl TODO: We may need to update NUT codebase to use NUT_STRARG() macro more +dnl often and consistently, or find a way to tweak upsdebugx() etc. varargs +AX_RUN_OR_LINK_IFELSE([AC_LANG_PROGRAM( + [#include ], + [printf("%s", NULL)] +)], + [ + AC_MSG_RESULT([ok]) + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [false]) + ], + [AC_MSG_RESULT([no]) + AC_DEFINE([REQUIRE_NUT_STRARG], [1], + [Define to 1 if your libc requires workarounds to print NULL values.]) + AC_MSG_WARN([Your C library requires workarounds to print NULL values; if something crashes with a segmentation fault (especially with verbose debug) - that may be why]) + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [true]) + ] +) +AC_LANG_POP([C]) + + AC_REPLACE_FUNCS(setenv strerror atexit) case ${target_os} in diff --git a/tests/.gitignore b/tests/.gitignore index 23e0f10359..9fa8deae00 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -6,6 +6,7 @@ /cppnit.trs /test-suite.log /selftest-rw/* +/nutlogtest-nofail.sh /nutlogtest /nutlogtest.log /nutlogtest.trs diff --git a/tests/Makefile.am b/tests/Makefile.am index e9cfd70770..5b58de509d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,13 +6,14 @@ all: $(TESTS) EXTRA_DIST = nut-driver-enumerator-test.sh nut-driver-enumerator-test--ups.conf -TESTS = nutlogtest +TESTS = CLEANFILES = *.trs *.log AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/drivers AM_CXXFLAGS = -I$(top_srcdir)/include check_PROGRAMS = $(TESTS) +check_SCRIPTS = # NUT Integration Testing suite check-NIT check-NIT-devel: @@ -21,6 +22,24 @@ check-NIT check-NIT-devel: nutlogtest_SOURCES = nutlogtest.c nutlogtest_LDADD = $(top_builddir)/common/libcommon.la +if REQUIRE_NUT_STRARG +check_SCRIPTS += nutlogtest-nofail.sh +CLEANFILES += nutlogtest-nofail.sh nutlogtest + +nutlogtest-nofail.sh: nutlogtest + @echo '#!/bin/sh' > $@ + @echo 'echo "WARNING: Your C library requires workarounds to print NULL values!" >&2' >> $@ + @echo 'echo "If nutlogtest below, or generally some NUT program, crashes with" >&2' >> $@ + @echo 'echo "a segmentation fault (especially with verbose debug) - that may be why" >&2' >> $@ + @echo 'SCRIPT_DIR="`dirname "$$0"`"' >> $@ + @echo '"$${SCRIPT_DIR}/nutlogtest" "$$@" || echo "nutlogtest FAILED but it was expected"' >> $@ + @chmod +x $@ + +# NOTE: Keep the line above empty! +else +TESTS += nutlogtest +endif + # Separate the .deps of other dirs from this one LINKED_SOURCE_FILES = hidparser.c From 3a8deafcac9fbb755e3e9ec0cee2c13ca5dca39a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 22 Dec 2022 17:17:59 +0100 Subject: [PATCH 0188/1232] configure.ac: fix AC_CHECK_FUNCS => AC_CHECK_DECLS where we care for includes [#1738] --- common/common.c | 8 ++++---- common/snprintf.c | 8 ++++---- configure.ac | 6 +++--- drivers/mge-hid.c | 8 +++++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/common/common.c b/common/common.c index 3eb3571345..4efdfe4451 100644 --- a/common/common.c +++ b/common/common.c @@ -32,7 +32,7 @@ #endif #include -#if !HAVE_REALPATH +#if !HAVE_DECL_REALPATH # include #endif @@ -1306,7 +1306,7 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l } while ((dirp = readdir(dp)) != NULL) { -#if !HAVE_REALPATH +#if !HAVE_DECL_REALPATH struct stat st; #endif @@ -1316,7 +1316,7 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l && dirp->d_name[base_libname_length] == '\0' /* avoid "*.dll.a" etc. */ ) { snprintf(current_test_path, LARGEBUF, "%s/%s", dirname, dirp->d_name); -#if HAVE_REALPATH +#if HAVE_DECL_REALPATH libname_path = realpath(current_test_path, NULL); #else /* Just check if candidate name is (points to?) valid file */ @@ -1353,7 +1353,7 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l } } # endif /* WIN32 */ -#endif /* HAVE_REALPATH */ +#endif /* HAVE_DECL_REALPATH */ upsdebugx(2,"Candidate path for lib %s is %s (realpath %s)", base_libname, current_test_path, diff --git a/common/snprintf.c b/common/snprintf.c index cd06bed561..c8c514578b 100644 --- a/common/snprintf.c +++ b/common/snprintf.c @@ -607,7 +607,7 @@ static LDOUBLE abs_val (LDOUBLE value) * FIXME: They are blindly expected (assumed?) to be available on Windows, * maybe better trust configure script macros on this? */ -# ifndef HAVE_POW10 +# if ! HAVE_DECL_POW10 static LDOUBLE pow10 (int exp) { LDOUBLE result = 1; @@ -620,9 +620,9 @@ static LDOUBLE pow10 (int exp) return result; } -# endif /* HAVE_POW10 */ +# endif /* HAVE_DECL_POW10 */ -# ifndef HAVE_ROUND +# if ! HAVE_DECL_ROUND static long round (LDOUBLE value) { long intpart; @@ -634,7 +634,7 @@ static long round (LDOUBLE value) return intpart; } -# endif /* HAVE_ROUND */ +# endif /* HAVE_DECL_ROUND */ # endif /* HAVE_FCVT */ #endif /* WIN32 */ diff --git a/configure.ac b/configure.ac index 1806b9dae9..da70360be2 100644 --- a/configure.ac +++ b/configure.ac @@ -224,7 +224,7 @@ AS_IF([test "$ac_cv_header_sys_time_h" = yes], and . This macro is deemed obsolete by autotools.]) ], []) -AC_CHECK_FUNCS(flock lockf fcvt fcvtl pow10 round abs_val abs) +AC_CHECK_FUNCS(flock lockf fcvt fcvtl abs_val abs) AC_CHECK_HEADER([float.h], [AC_DEFINE([HAVE_FLOAT_H], [1], @@ -233,7 +233,7 @@ AC_CHECK_HEADER([math.h], [AC_DEFINE([HAVE_MATH_H], [1], [Define to 1 if you have .])]) -AC_CHECK_FUNCS(fabs fabsf fabsl, [], [], +AC_CHECK_DECLS([fabs, fabsf, fabsl, pow10, round], [], [], [#ifdef HAVE_MATH_H # include #endif @@ -250,7 +250,7 @@ AC_CHECK_HEADER([stdlib.h], [AC_DEFINE([HAVE_STDLIB_H], [1], [Define to 1 if you have .])]) -AC_CHECK_FUNCS(realpath, [], [], +AC_CHECK_DECLS(realpath, [], [], [#ifdef HAVE_LIMITS_H # include #endif diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 93ffcba66b..3b152f374b 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -186,8 +186,10 @@ static char mge_scratch_buf[20]; /* Internal flag to process battery status (CHRG/DISCHRG) and ABM */ static int advanced_battery_monitoring = ABM_UNKNOWN; -/* TODO: Lifted from strptime.c... maybe should externalize the fallback? */ -#ifndef HAVE_ROUND +/* TODO: Lifted from strptime.c... maybe should externalize the fallback? + * NOTE: HAVE_DECL_* are always defined, 0 or 1. Many other flags are not. + */ +#if ! HAVE_DECL_ROUND # ifndef WIN32 static long round (double value) # else @@ -203,7 +205,7 @@ static long round (LDOUBLE value) return intpart; } -#endif /* HAVE_ROUND */ +#endif /* HAVE_DECL_ROUND */ /* Used to store internally if ABM is enabled or not */ static const char *eaton_abm_enabled_fun(double value) From 43d5213166214e38558b9097fbf1f5ad5600862a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 16:25:16 +0100 Subject: [PATCH 0189/1232] tools/gitlog2changelog.py: support Python 3.6 (and older 3.x) regarding UTF-8 content of git changelog --- tools/gitlog2changelog.py.in | 44 +++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 5d882cbe37..fe0e9103b9 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -6,17 +6,41 @@ import string, re, os from textwrap import TextWrapper import sys +import subprocess -rev_range = '' +rev_range = 'HEAD' if len(sys.argv) > 1: base = sys.argv[1] rev_range = '%s..HEAD' % base # Execute git log with the desired command line options. -fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') +# Support Python2 and Python3 (esp. 3.6 and earlier) semantics +# with regard to utf-8 content support (avois ascii decoding in Py3) +fin_mode = 0 +# Remove trailing end of line? spitlines() in py3 variant takes care of them +fin_chop = 0 +try: + p = subprocess.Popen( + ['git', 'log', '--summary', '--stat', '--no-merges', '--date=short', ('%s' % rev_range)], + encoding='utf-8', close_fds = True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + fin, ferr = p.communicate() + if p.wait() != 0: + print ("ERROR getting git changelog") + system.exit(1) + fin = fin.splitlines() + fin_mode = 3 +except TypeError: + fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') + fin_mode = 2 + fin_chop = 1 + # Create a ChangeLog file in the current directory. -fout = open('ChangeLog', 'w') +if fin_mode == 3: + fout = open('ChangeLog', 'w', encoding='UTF-8') +else: + fout = open('ChangeLog', 'w') # Set up the loop variables in order to locate the blocks we want authorFound = False @@ -49,7 +73,7 @@ for line in fin: authorList = re.split(': ', line, 1) try: author = authorList[1] - author = author[0:len(author)-1] + author = author[0:len(author) - fin_chop] authorFound = True except: print ("Could not parse authorList = '%s'" % (line)) @@ -59,7 +83,7 @@ for line in fin: dateList = re.split(': ', line, 1) try: date = dateList[1] - date = date[0:len(date)-1] + date = date[0:len(date) - fin_chop] dateFound = True except: print ("Could not parse dateList = '%s'" % (line)) @@ -75,12 +99,12 @@ for line in fin: # Extract the actual commit message for this commit elif authorFound & dateFound & messageFound == False: # Find the commit message if we can - if len(line) == 1: + if len(line) == fin_chop: if messageNL: messageFound = True else: messageNL = True - elif len(line) == 4: + elif len(line) == 3 + fin_chop: messageFound = True else: if len(message) == 0: @@ -129,5 +153,9 @@ for line in fin: prevAuthorLine = authorLine # Close the input and output lines now that we are finished. -fin.close() +if fin_mode == 3: + p.stdout.close() + p.stderr.close() +else: + fin.close() fout.close() From fd57fd7b090ef7053a55550ae772fcee725dc4cb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 16:25:53 +0100 Subject: [PATCH 0190/1232] tools/gitlog2changelog.py: avoid prefixing file list to messages whose commit comment starts with equivalent list --- tools/gitlog2changelog.py.in | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index fe0e9103b9..dfdf2fb403 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -137,7 +137,23 @@ for line in fin: # Assemble the actual commit message line(s) and limit the line length # to 80 characters. - commitLine = "* " + files + ": " + message + # Avoid printing same (or equivalen) filename lists twice, if commit + # message starts with them. + if message.startswith(files + ":"): + commitLine = "* " + message + else: + namesF = None + namesM = None + try: + namesM = sorted(re.split(r'[ ,]', message.split(":")[0])) + namesF = sorted(re.split(r'[ ,]', files)) + except: + pass + + if namesM is not None and namesM == namesF: + commitLine = "* " + message + else: + commitLine = "* " + files + ": " + message # Write out the commit line fout.write(wrapper.fill(commitLine) + "\n") From be164190863a4504520c01128d455a55f0e09a96 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 20:59:47 +0100 Subject: [PATCH 0191/1232] configure.ac, scripts/subdriver/gen-*.sh: introduce WITH_UNMAPPED_DATA_POINTS flag [#1699] --- NEWS | 5 +++++ configure.ac | 12 ++++++++++++ docs/configure.txt | 7 +++++++ docs/hid-subdrivers.txt | 5 +++++ docs/snmp-subdrivers.txt | 6 ++++++ scripts/subdriver/gen-snmp-subdriver.sh | 8 +++++++- scripts/subdriver/gen-usbhid-subdriver.sh | 5 +++++ 7 files changed, 47 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 506a175623..a6acc30a26 100644 --- a/NEWS +++ b/NEWS @@ -173,6 +173,11 @@ https://github.com/networkupstools/nut/milestone/8 to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] + - `configure` script enhanced: `--with-unmapped-data-points` option allows + to build SNMP and USB-HID subdrivers with entries discovered by the scripts + which generated them from data walks, but developers did not rename yet + to NUT mappings conforming to `docs/nut-names.txt` standards [#1699] + - PyNUT.py version bumped to 1.5.0 with some improvements: * `ListClients()` method fixed (was broken in many ways), and is now CI-tested [#549] diff --git a/configure.ac b/configure.ac index 4ee8734e36..1e09c4b969 100644 --- a/configure.ac +++ b/configure.ac @@ -1003,6 +1003,18 @@ dnl a bit below to be grouped with their additional with/enable help. NUT_ARG_WITH([dev], [build and install the development files], [no]) +dnl Activate WITH_UNMAPPED_DATA_POINTS for troubleshooting and evolution? +dnl Note that production drivers must conform to docs/nut-names.txt +NUT_ARG_WITH([unmapped-data-points], + [represent USB-HID and SNMP data points discovered during subdriver generation but not mapped to nut-names yet], + [no]) +AS_IF([test x"${nut_with_unmapped_data_points}" = xyes], + [AC_DEFINE(WITH_UNMAPPED_DATA_POINTS, 1, + [Define to enable data points discovered during subdriver generation but not mapped to nut-names yet])], + [AC_DEFINE(WITH_UNMAPPED_DATA_POINTS, 0, + [Define to enable data points discovered during subdriver generation but not mapped to nut-names yet])] +) + dnl The NUT legacy option was --with-doc; however to simplify configuration dnl in some common packaging frameworks, we also allow --with-docs as dnl a second-class citizen (if both are set, the old option name wins). diff --git a/docs/configure.txt b/docs/configure.txt index 2d90384d5d..91c2336db1 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -244,6 +244,13 @@ ever-changing `Makefile.am` content after Git updates or editing. Activate recipes for static analysis with `cppcheck` tools (if available). + --with-unmapped-data-points (default: no) + +Build SNMP and USB-HID subdrivers with entries discovered by the scripts +which generated them from data walks, but developers did not rename yet +to NUT mappings conforming to `docs/nut-names.txt` standards. Production +driver builds must not include any non-standard names. + I want it all! ~~~~~~~~~~~~~~ diff --git a/docs/hid-subdrivers.txt b/docs/hid-subdrivers.txt index 6ed94497ac..731fdcfa38 100644 --- a/docs/hid-subdrivers.txt +++ b/docs/hid-subdrivers.txt @@ -260,6 +260,11 @@ subdrivers are written: - powercom-hid.c/h - tripplite-hid.c/h +NOTE: To test existing data points (including those not yet translated +to standard NUT mappings conforming to <>), you can use custom drivers built after you +`./configure --with-unmapped-data-points`. +Production driver builds must not include any non-standard names. Fixing report descriptors ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/snmp-subdrivers.txt b/docs/snmp-subdrivers.txt index d71c35f628..ca96b4097d 100644 --- a/docs/snmp-subdrivers.txt +++ b/docs/snmp-subdrivers.txt @@ -238,6 +238,12 @@ In the above example, the right NUT variable is obviously "device.model". The MIB definition file (.mib) also contains some description of these OIDs, along with the possible enumerated values. +NOTE: To test existing data points (including those not yet translated +to standard NUT mappings conforming to <>), you can use custom drivers built after you +`./configure --with-unmapped-data-points`. +Production driver builds must not include any non-standard names. + //////////////////////////////////////////////////////////////////////////////// FIXME: diff --git a/scripts/subdriver/gen-snmp-subdriver.sh b/scripts/subdriver/gen-snmp-subdriver.sh index c6d52ecbdc..4683aff9a5 100755 --- a/scripts/subdriver/gen-snmp-subdriver.sh +++ b/scripts/subdriver/gen-snmp-subdriver.sh @@ -3,7 +3,7 @@ # an auxiliary script to produce a "stub" snmp-ups subdriver from # SNMP data from a real agent or from dump files # -# Version: 0.14 +# Version: 0.15 # # See also: docs/snmp-subdrivers.txt # @@ -256,6 +256,11 @@ generate_C() { { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL }, { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL }, { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, + +/* Please revise values discovered by data walk for mappings to + * docs/nut-names.txt and group the rest under the ifdef below: + */ +#if WITH_UNMAPPED_DATA_POINTS EOF # extract OID string paths, one by one @@ -279,6 +284,7 @@ EOF # append footer (TABs not stripped): cat >> "$CFILE" <> "$CFILE" < Date: Sun, 25 Dec 2022 20:18:59 +0100 Subject: [PATCH 0192/1232] drivers/*-mib.c: fence WITH_UNMAPPED_DATA_POINTS [#1699] --- drivers/apc-ats-mib.c | 4 +-- drivers/apc-epdu-mib.c | 2 +- drivers/apc-mib.c | 4 +-- drivers/apc-pdu-mib.c | 4 +-- drivers/compaq-mib.c | 6 +++-- drivers/delta_ups-mib.c | 4 +-- drivers/eaton-ats16-nm2-mib.c | 4 +-- drivers/eaton-ats16-nmc-mib.c | 4 +-- drivers/eaton-ats30-mib.c | 20 +++++++-------- drivers/eaton-pdu-marlin-mib.c | 18 ++++++++------ drivers/eaton-pdu-nlogic-mib.c | 41 ++++++++++++++++--------------- drivers/emerson-avocent-pdu-mib.c | 6 +++-- drivers/hpe-pdu-mib.c | 32 +++++++++++++++--------- drivers/hpe-pdu3-cis-mib.c | 12 +++++---- drivers/huawei-mib.c | 6 ++--- drivers/raritan-px2-mib.c | 8 +++--- 16 files changed, 97 insertions(+), 78 deletions(-) diff --git a/drivers/apc-ats-mib.c b/drivers/apc-ats-mib.c index 56a6779c8e..5cb8cc50be 100644 --- a/drivers/apc-ats-mib.c +++ b/drivers/apc-ats-mib.c @@ -144,7 +144,7 @@ static snmp_info_t apc_ats_mib[] = { { "outlet.group.%i.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.15.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL }, -#if 0 /* FIXME: Remaining data to be processed */ +#if WITH_UNMAPPED_DATA_POINTS /* FIXME: Remaining data to be processed */ /* atsIdentDeviceRating.0 = INTEGER: 32 */ { "unmapped.atsIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.9.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationNumInputs.0 = INTEGER: 2 */ @@ -444,7 +444,7 @@ static snmp_info_t apc_ats_mib[] = { { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentPower.3 = INTEGER: -1 */ { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.3", NULL, SU_FLAG_OK, NULL }, -#endif /* 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/apc-epdu-mib.c b/drivers/apc-epdu-mib.c index e513252b63..bc8b288b11 100644 --- a/drivers/apc-epdu-mib.c +++ b/drivers/apc-epdu-mib.c @@ -106,7 +106,7 @@ static snmp_info_t apc_epdu_mib[] = { /* ePDUOutletStatusState.%i = INTEGER: off(1) */ { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.30.6.1.1.4.%i", "yes", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_epdu_sw_outlet_switchability_info[0] }, -#if 0 /* keep following scan for future development */ +#if WITH_UNMAPPED_DATA_POINTS /* keep following scan for future development */ /* iso.3.6.1.4.1.318.1.1.30.1.0 = INTEGER: 1 */ { "unmapped.iso", 0, 1, ".1.3.6.1.4.1.318.1.1.30.1.0", NULL, SU_FLAG_OK, NULL }, /* iso.3.6.1.4.1.318.1.1.30.2.1.1.1.1 = INTEGER: 1 */ diff --git a/drivers/apc-mib.c b/drivers/apc-mib.c index 1ac0a27816..a716844f13 100644 --- a/drivers/apc-mib.c +++ b/drivers/apc-mib.c @@ -269,14 +269,14 @@ static snmp_info_t apcc_mib[] = { { "output.voltage.nominal", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.1.0", "", SU_TYPE_INT | SU_FLAG_OK, NULL }, /* Measure-UPS ambient variables */ -/* Environmental sensors (AP9612TH and others) */ + /* Environmental sensors (AP9612TH and others) */ { "ambient.temperature", 0, 1, ".1.3.6.1.4.1.318.1.1.2.1.1.0", "", SU_FLAG_OK, NULL }, { "ambient.1.temperature.alarm.high", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.3.1", "", SU_FLAG_OK, NULL }, { "ambient.1.temperature.alarm.low", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.4.1", "", SU_FLAG_OK, NULL }, { "ambient.humidity", 0, 1, ".1.3.6.1.4.1.318.1.1.2.1.2.0", "", SU_FLAG_OK, NULL }, { "ambient.1.humidity.alarm.high", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.6.1", "", SU_FLAG_OK, NULL }, { "ambient.1.humidity.alarm.low", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.7.1", "", SU_FLAG_OK, NULL }, -/* IEM: integrated environment monitor probe */ + /* IEM: integrated environment monitor probe */ { "ambient.temperature", 0, 1, APCC_OID_IEM_TEMP, "", SU_FLAG_OK, NULL }, { "ambient.humidity", 0, 1, APCC_OID_IEM_HUMID, "", SU_FLAG_OK, NULL }, diff --git a/drivers/apc-pdu-mib.c b/drivers/apc-pdu-mib.c index 38963d577e..2ca28df12c 100644 --- a/drivers/apc-pdu-mib.c +++ b/drivers/apc-pdu-mib.c @@ -101,7 +101,7 @@ static snmp_info_t apc_pdu_mib[] = { -#if 0 /* keep following scan for future development */ +#if WITH_UNMAPPED_DATA_POINTS /* keep following scan for future development */ /* sPDUMasterControlSwitch.0 = INTEGER: noCommand(6) */ { "unmapped.sPDUMasterControlSwitch", 0, 1, ".1.3.6.1.4.1.318.1.1.4.2.1.0", NULL, SU_FLAG_OK, NULL }, @@ -960,7 +960,7 @@ static snmp_info_t apc_pdu_mib[] = { { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.4.0", NULL, SU_FLAG_OK, NULL }, /* experimental.7.5.0 = INTEGER: 3 */ { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.5.0", NULL, SU_FLAG_OK, NULL }, -#endif /* scan result */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ diff --git a/drivers/compaq-mib.c b/drivers/compaq-mib.c index 114299aa70..4fdd9f9435 100644 --- a/drivers/compaq-mib.c +++ b/drivers/compaq-mib.c @@ -291,10 +291,12 @@ static snmp_info_t cpqpower_mib[] = { SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.count", 0, 1, ".1.3.6.1.4.1.232.165.3.10.1.0", "0", 0, NULL }, /* upsNumReceptacles */ -/* { "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL, NULL }, +/* + { "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL, NULL }, { "outlet.voltage", 0, 0.001, AR_OID_UNIT_VOLTAGE ".0", NULL, 0, NULL, NULL }, { "outlet.realpower", 0, 1.0, AR_OID_UNIT_ACTIVEPOWER ".0", NULL, 0, NULL, NULL }, - { "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL, NULL }, */ + { "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL, NULL }, +*/ /* outlet template definition */ /* FIXME always true? */ diff --git a/drivers/delta_ups-mib.c b/drivers/delta_ups-mib.c index 770b0d7e80..08b810439d 100644 --- a/drivers/delta_ups-mib.c +++ b/drivers/delta_ups-mib.c @@ -129,7 +129,7 @@ static snmp_info_t delta_ups_mib[] = { * Mostly the first field (string) is to be changed * Check docs/nut-names.txt for the right variable names */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* dupsIdentName.0 = "" */ { "unmapped.dupsIdentName", 0, 1, ".1.3.6.1.4.1.2254.2.4.1.5.0", NULL, SU_FLAG_OK, NULL }, /* dupsAttachedDevices.0 = "" */ @@ -356,7 +356,7 @@ static snmp_info_t delta_ups_mib[] = { { "unmapped.dupsAlarmEnvRelay3", 0, 1, ".1.3.6.1.4.1.2254.2.4.10.13.0", NULL, SU_FLAG_OK, NULL }, /* dupsAlarmEnvRelay4.0 = INTEGER: off(0) */ { "unmapped.dupsAlarmEnvRelay4", 0, 1, ".1.3.6.1.4.1.2254.2.4.10.14.0", NULL, SU_FLAG_OK, NULL }, -#endif /* #if 0 */ +#endif /* #if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/eaton-ats16-nm2-mib.c b/drivers/eaton-ats16-nm2-mib.c index 1980c30039..ce4145b082 100644 --- a/drivers/eaton-ats16-nm2-mib.c +++ b/drivers/eaton-ats16-nm2-mib.c @@ -186,7 +186,7 @@ static snmp_info_t eaton_ats16_nm2_mib[] = { ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0] }, -#if 0 /* FIXME: Remaining data to be processed */ +#if WITH_UNMAPPED_DATA_POINTS /* FIXME: Remaining data to be processed */ /* ats2InputStatusDephasing.0 = INTEGER: normal(1) */ { "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusIndex.source1 = INTEGER: source1(1) */ @@ -262,7 +262,7 @@ static snmp_info_t eaton_ats16_nm2_mib[] = { { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactDescr.2 = STRING: Input #2 */ { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL }, -#endif /* if 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/eaton-ats16-nmc-mib.c b/drivers/eaton-ats16-nmc-mib.c index 8cf2496bfd..be53725fef 100644 --- a/drivers/eaton-ats16-nmc-mib.c +++ b/drivers/eaton-ats16-nmc-mib.c @@ -185,7 +185,7 @@ static snmp_info_t eaton_ats16_nmc_mib[] = { ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0]}, -#if 0 /* FIXME: Remaining data to be processed */ +#if WITH_UNMAPPED_DATA_POINTS /* FIXME: Remaining data to be processed */ /* ats2InputStatusDephasing.0 = INTEGER: normal(1) */ { "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusIndex.source1 = INTEGER: source1(1) */ @@ -257,7 +257,7 @@ static snmp_info_t eaton_ats16_nmc_mib[] = { { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactDescr.2 = STRING: Input #2 */ { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL }, -#endif /* if 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/eaton-ats30-mib.c b/drivers/eaton-ats30-mib.c index ec03aab22f..0b2032fb1f 100644 --- a/drivers/eaton-ats30-mib.c +++ b/drivers/eaton-ats30-mib.c @@ -132,7 +132,7 @@ static snmp_info_t eaton_ats30_mib[] = { /* atsStatus */ /* ========= */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* NOTE: Unused OIDs are left as comments for potential future improvements */ /* enterprises.534.10.1.4.1.0 = INTEGER: 7 */ { "unmapped.atsInputFlowIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.1.0", NULL, SU_FLAG_OK, NULL }, @@ -198,12 +198,12 @@ static snmp_info_t eaton_ats30_mib[] = { { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.11.2 = INTEGER: 1 */ { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.2", NULL, SU_FLAG_OK, NULL }, -#endif /* 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* enterprises.atsFailureIndicator = INTEGER: 0 */ { "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.1.4.5.0", NULL, SU_FLAG_OK, eaton_ats30_status_info }, -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* enterprises.534.10.1.4.6.1.0 = INTEGER: 2 -- atsFailure start */ { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.6.2.0 = INTEGER: 2 */ @@ -212,11 +212,11 @@ static snmp_info_t eaton_ats30_mib[] = { { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.6.4.0 = INTEGER: 2 */ { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.4.0", NULL, SU_FLAG_OK, NULL }, -#endif /* 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* atsLog */ /* ====== */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* We are not interested in log */ /* enterprises.534.10.1.5.1.0 = INTEGER: 272 */ { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.1.0", NULL, SU_FLAG_OK, NULL }, @@ -300,11 +300,11 @@ static snmp_info_t eaton_ats30_mib[] = { { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.9", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.10 = STRING: "07:31:28 05/12/2016" */ { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.10", NULL, SU_FLAG_OK, NULL }, -#endif /* 0 */ +#endif /* WITH_UNMAPPED_DATA_POINTS */ /* atsConfig */ /* ========= */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* enterprises.534.10.1.6.1.1.0 = INTEGER: 538562409 */ { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.1.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.1.2.0 = STRING: "01/24/2017" */ @@ -343,7 +343,7 @@ static snmp_info_t eaton_ats30_mib[] = { { "unmapped.atsConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.1.6.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.4.0 = INTEGER: 26 */ { "unmapped.atsConfigRandomTime", 0, 1, ".1.3.6.1.4.1.534.10.1.6.4.0", NULL, SU_FLAG_OK, NULL }, -#endif /* 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* enterprises.534.10.1.6.5.0 = INTEGER: 1 */ { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.5.0", NULL, SU_FLAG_OK, NULL }, @@ -355,7 +355,7 @@ static snmp_info_t eaton_ats30_mib[] = { /* atsUpgrade */ /* ========== */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* We are not interested in atsUpgrade */ /* enterprises.534.10.1.7.1.0 = INTEGER: 1 */ /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.1.0", NULL, SU_FLAG_OK, NULL }, */ @@ -363,7 +363,7 @@ static snmp_info_t eaton_ats30_mib[] = { /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.2.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.7.3.0 = INTEGER: 0 */ /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.3.0", NULL, SU_FLAG_OK, NULL }, */ -#endif /* 0 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index bed4bbef53..b5f5a8b7fc 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -706,10 +706,11 @@ static snmp_info_t eaton_marlin_mib[] = { * inputFeedName.0.1 = Value (OctetString): Feed A */ /* FIXME: SU_FLAG_SEMI_STATIC or SU_FLAG_SETTING => refreshed from time to time or upon call to setvar */ -/* { "input.%i.feed.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, - * ".1.3.6.1.4.1.534.6.6.7.3.1.1.10.%i.%i", - * NULL, SU_FLAG_SEMI_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, - */ +/* + { "input.%i.feed.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.3.1.1.10.%i.%i", + NULL, SU_FLAG_SEMI_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, +*/ { "input.feed.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.1.1.10.%i.1", NULL, SU_FLAG_SEMI_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, @@ -717,10 +718,11 @@ static snmp_info_t eaton_marlin_mib[] = { * inputFeedColor.0.1 = Gauge32: 0 (black) */ /* FIXME: RFC on key name is needed when backporting to NUT upstream */ -/* { "input.%i.feed.color", 0, 1, - * ".1.3.6.1.4.1.534.6.6.7.3.1.1.9.%i.%i", - * NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, - */ +/* + { "input.%i.feed.color", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.3.1.1.9.%i.%i", + NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, +*/ { "input.feed.color", 0, 1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.9.%i.1", NULL, SU_FLAG_SEMI_STATIC | SU_FLAG_OK | SU_TYPE_DAISY_1, NULL }, diff --git a/drivers/eaton-pdu-nlogic-mib.c b/drivers/eaton-pdu-nlogic-mib.c index e1162e32d1..5a97fadd26 100644 --- a/drivers/eaton-pdu-nlogic-mib.c +++ b/drivers/eaton-pdu-nlogic-mib.c @@ -278,8 +278,9 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { ".1.3.6.1.4.1.534.7.1.5.2.1.10.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL }, + set "outlet.%i.delay.start" + set itself to delayedReboot (6), // &eaton_nlogic_outlet_delayed_reboot_info[0] +#endif - +#if WITH_UNMAPPED_DATA_POINTS /* pduIPv4Address.1 = IpAddress: 192.168.1.55 */ { "unmapped.pduIPv4Address", 0, 1, ".1.3.6.1.4.1.534.7.1.1.2.1.15.1", NULL, SU_FLAG_OK, NULL }, /* pduIPv6Address.1 = STRING: "FE80::CA45:44FF:FE30:9414" */ @@ -303,8 +304,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { /* pduConfigNetworkManagementCardReset.1 = INTEGER: 0 */ { "unmapped.pduConfigNetworkManagementCardReset", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.10.1", NULL, SU_FLAG_OK, NULL }, -/* pduConfigDaisyChainStatus.1 = INTEGER: 0 */ -{ "unmapped.pduConfigDaisyChainStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.11.1", NULL, SU_FLAG_OK, NULL }, + /* pduConfigDaisyChainStatus.1 = INTEGER: 0 */ + { "unmapped.pduConfigDaisyChainStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.1.3.1.11.1", NULL, SU_FLAG_OK, NULL }, /* pduInputFrequencyStatus.1 = INTEGER: 1 */ { "unmapped.pduInputFrequencyStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.2.1.1.3.1", NULL, SU_FLAG_OK, NULL }, @@ -911,8 +912,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.11", NULL, SU_FLAG_OK, NULL }, /* pduGroupCurrentPercentLoad.1.12 = INTEGER: 0 */ { "unmapped.pduGroupCurrentPercentLoad", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.18.1.12", NULL, SU_FLAG_OK, NULL }, -/* pduGroupPowerVA.1.1 = INTEGER: 0 */ -{ "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerVA.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.1", NULL, SU_FLAG_OK, NULL }, /* pduGroupPowerVA.1.2 = INTEGER: 0 */ { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.2", NULL, SU_FLAG_OK, NULL }, /* pduGroupPowerVA.1.3 = INTEGER: 0 */ @@ -935,8 +936,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.11", NULL, SU_FLAG_OK, NULL }, /* pduGroupPowerVA.1.12 = INTEGER: 0 */ { "unmapped.pduGroupPowerVA", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.19.1.12", NULL, SU_FLAG_OK, NULL }, -/* pduGroupPowerWatts.1.1 = INTEGER: 0 */ -{ "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduGroupPowerWatts.1.1 = INTEGER: 0 */ + { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.1", NULL, SU_FLAG_OK, NULL }, /* pduGroupPowerWatts.1.2 = INTEGER: 0 */ { "unmapped.pduGroupPowerWatts", 0, 1, ".1.3.6.1.4.1.534.7.1.3.1.1.20.1.2", NULL, SU_FLAG_OK, NULL }, /* pduGroupPowerWatts.1.3 = INTEGER: 0 */ @@ -1203,8 +1204,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.5", NULL, SU_FLAG_OK, NULL }, /* pduTemperatureProbeStatus.1.6 = INTEGER: 1 */ { "unmapped.pduTemperatureProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.3.1.6", NULL, SU_FLAG_OK, NULL }, -/* pduTemperatureValue.1.1 = INTEGER: 0 */ -{ "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduTemperatureValue.1.1 = INTEGER: 0 */ + { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, /* pduTemperatureValue.1.2 = INTEGER: 0 */ { "unmapped.pduTemperatureValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, /* pduTemperatureValue.1.3 = INTEGER: 0 */ @@ -1323,8 +1324,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.5", NULL, SU_FLAG_OK, NULL }, /* pduHumidityProbeStatus.1.6 = INTEGER: 1 */ { "unmapped.pduHumidityProbeStatus", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.3.1.6", NULL, SU_FLAG_OK, NULL }, -/* pduHumidityValue.1.1 = INTEGER: 0 */ -{ "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduHumidityValue.1.1 = INTEGER: 0 */ + { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.1", NULL, SU_FLAG_OK, NULL }, /* pduHumidityValue.1.2 = INTEGER: 0 */ { "unmapped.pduHumidityValue", 0, 1, ".1.3.6.1.4.1.534.7.1.4.3.1.4.1.2", NULL, SU_FLAG_OK, NULL }, /* pduHumidityValue.1.3 = INTEGER: 0 */ @@ -2999,8 +3000,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduOutletActivePowerThCtrl", 0, 1, ".1.3.6.1.4.1.534.7.1.5.1.1.21.1.48", NULL, SU_FLAG_OK, NULL }, -/* pduOutletControlOffCmd.1.1 = INTEGER: -1 */ -{ "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOffCmd.1.1 = INTEGER: -1 */ + { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.1", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOffCmd.1.2 = INTEGER: -1 */ { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.2", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOffCmd.1.3 = INTEGER: -1 */ @@ -3095,8 +3096,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.47", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOffCmd.1.48 = INTEGER: 0 */ { "unmapped.pduOutletControlOffCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.2.1.48", NULL, SU_FLAG_OK, NULL }, -/* pduOutletControlOnCmd.1.1 = INTEGER: -1 */ -{ "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlOnCmd.1.1 = INTEGER: -1 */ + { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.1", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOnCmd.1.2 = INTEGER: -1 */ { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.2", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOnCmd.1.3 = INTEGER: -1 */ @@ -3191,8 +3192,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.47", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlOnCmd.1.48 = INTEGER: 0 */ { "unmapped.pduOutletControlOnCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.3.1.48", NULL, SU_FLAG_OK, NULL }, -/* pduOutletControlRebootCmd.1.1 = INTEGER: -1 */ -{ "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlRebootCmd.1.1 = INTEGER: -1 */ + { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.1", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlRebootCmd.1.2 = INTEGER: -1 */ { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.2", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlRebootCmd.1.3 = INTEGER: -1 */ @@ -3287,8 +3288,8 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.47", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlRebootCmd.1.48 = INTEGER: 0 */ { "unmapped.pduOutletControlRebootCmd", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.4.1.48", NULL, SU_FLAG_OK, NULL }, -/* pduOutletControlPowerOnState.1.1 = INTEGER: 2 */ -{ "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, + /* pduOutletControlPowerOnState.1.1 = INTEGER: 2 */ + { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.1", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlPowerOnState.1.2 = INTEGER: 2 */ { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.2", NULL, SU_FLAG_OK, NULL }, /* pduOutletControlPowerOnState.1.3 = INTEGER: 2 */ @@ -3384,7 +3385,7 @@ static snmp_info_t eaton_pdu_nlogic_mib[] = { /* pduOutletControlPowerOnState.1.48 = INTEGER: 0 */ { "unmapped.pduOutletControlPowerOnState", 0, 1, ".1.3.6.1.4.1.534.7.1.5.2.1.5.1.48", NULL, SU_FLAG_OK, NULL }, -#endif +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/emerson-avocent-pdu-mib.c b/drivers/emerson-avocent-pdu-mib.c index cffe5554d3..8ca90d8a3c 100644 --- a/drivers/emerson-avocent-pdu-mib.c +++ b/drivers/emerson-avocent-pdu-mib.c @@ -62,7 +62,8 @@ static info_lkp_t avocent_outlet_status_info[] = { { 1, "off", NULL, NULL }, { 2, "on", NULL, NULL }, -/* { 3, "offLocked", NULL, NULL }, +/* + { 3, "offLocked", NULL, NULL }, { 4, "onLocked", NULL, NULL }, { 5, "offCycle", NULL, NULL }, { 6, "onPendingOff", NULL, NULL }, @@ -71,7 +72,8 @@ static info_lkp_t avocent_outlet_status_info[] = { { 9, "notSet", NULL, NULL }, { 10, "onFixed", NULL, NULL }, { 11, "offShutdown", NULL, NULL }, - { 12, "tripped", NULL, NULL },*/ + { 12, "tripped", NULL, NULL }, +*/ { 0, NULL, NULL, NULL } }; diff --git a/drivers/hpe-pdu-mib.c b/drivers/hpe-pdu-mib.c index bf429878b0..0193f619ba 100644 --- a/drivers/hpe-pdu-mib.c +++ b/drivers/hpe-pdu-mib.c @@ -547,10 +547,13 @@ static snmp_info_t hpe_pdu_mib[] = { NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, /* TODO: handle statistics */ - /* pdu2InputPowerWattHour.0 = INTEGER: 91819 - { "unmapped.pdu2InputPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, */ - /* pdu2InputPowerWattHourTimer.0 = STRING: "16/10/2017,17:58:53" - { "unmapped.pdu2InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.2.1.1.7.0", NULL, SU_FLAG_OK, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + /* pdu2InputPowerWattHour.0 = INTEGER: 91819 */ + { "unmapped.pdu2InputPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, + /* pdu2InputPowerWattHourTimer.0 = STRING: "16/10/2017,17:58:53" */ + { "unmapped.pdu2InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.2.1.1.7.0", NULL, SU_FLAG_OK, NULL }, +#endif /* #if WIH_UNMAPPED_DATA_POINTS */ + /* pdu2InputPowerFactor.0 = INTEGER: 483 */ { "input.powerfactor", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.1.1.8.%i", @@ -736,12 +739,15 @@ static snmp_info_t hpe_pdu_mib[] = { { "outlet.%i.powerfactor", 0, 0.001, ".1.3.6.1.4.1.232.165.7.5.1.1.17.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* TODO: handle statistics */ +#if WITH_UNMAPPED_DATA_POINTS /* pdu2OutletWh.0.1 = INTEGER: 1167 - * Note: setting this to zero resets the counter and timestamp => instcmd ???counter???.reset - { "unmapped.pdu2OutletWh", 0, 1, ".1.3.6.1.4.1.232.165.7.5.1.1.15.%i.%i", NULL, SU_FLAG_OK, NULL }, */ - /* pdu2OutletWhTimer.0.1 = STRING: "25/03/2016,09:03:26" - { "unmapped.pdu2OutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.5.1.1.16.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + * Note: setting this to zero resets the counter and timestamp => instcmd ???counter???.reset */ + { "unmapped.pdu2OutletWh", 0, 1, ".1.3.6.1.4.1.232.165.7.5.1.1.15.%i.%i", NULL, SU_FLAG_OK, NULL }, + /* pdu2OutletWhTimer.0.1 = STRING: "25/03/2016,09:03:26" */ + { "unmapped.pdu2OutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.5.1.1.16.%i.%i", NULL, SU_FLAG_OK, NULL }, +#endif /* #if WITH_UNMAPPED_DATA_POINTS */ /* Outlet groups collection */ /* pdu2GroupCount.0 = INTEGER: 3 */ @@ -857,11 +863,13 @@ static snmp_info_t hpe_pdu_mib[] = { NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, /* TODO: handle statistics */ +#if WITH_UNMAPPED_DATA_POINTS /* pdu2GroupPowerWattHour.0.%i = INTEGER: 1373 - * Note: setting this to zero resets the counter and timestamp => instcmd .reset - { "unmapped.pdu2GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.3.1.1.22.%i.%i", NULL, SU_FLAG_OK, NULL }, */ - /* pdu2GroupPowerWattHourTimer.0.%i = STRING: "25/03/2016,09:01:16" - { "unmapped.pdu2GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.3.1.1.23.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + * Note: setting this to zero resets the counter and timestamp => instcmd .reset */ + { "unmapped.pdu2GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.3.1.1.22.%i.%i", NULL, SU_FLAG_OK, NULL }, + /* pdu2GroupPowerWattHourTimer.0.%i = STRING: "25/03/2016,09:01:16" */ + { "unmapped.pdu2GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.3.1.1.23.%i.%i", NULL, SU_FLAG_OK, NULL }, +#endif /* #if WITH_UNMAPPED_DATA_POINTS */ /* instant commands. */ /* TODO: handle delays (outlet.%i.{on,off}.delay) */ diff --git a/drivers/hpe-pdu3-cis-mib.c b/drivers/hpe-pdu3-cis-mib.c index f7f7559867..5b6bf9ef86 100644 --- a/drivers/hpe-pdu3-cis-mib.c +++ b/drivers/hpe-pdu3-cis-mib.c @@ -88,7 +88,9 @@ static snmp_info_t hpe_pdu3_cis_mib[] = { { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL }, { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, /* pdu3NumberPDU.0 = INTEGER: 1 (for daisychain support) */ -// { "device.count", 0, 1, ".1.3.6.1.4.1.232.165.11.1.1.0", NULL, SU_FLAG_OK, NULL }, +/* + { "device.count", 0, 1, ".1.3.6.1.4.1.232.165.11.1.1.0", NULL, SU_FLAG_OK, NULL }, +*/ /* pdu3Manufacturer.1 = STRING: "HPE" */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.1.2.1.4.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, @@ -278,7 +280,7 @@ static snmp_info_t hpe_pdu3_cis_mib[] = { NULL, SU_OUTLET /*| SU_TYPE_DAISY_1*/, NULL }, #endif -#ifdef WITH_UNMAPPED_DATA_POINTS +#if WITH_UNMAPPED_DATA_POINTS /* pdu3IdentIndex.1 = INTEGER: 1 */ { "unmapped.pdu3IdentIndex", 0, 1, ".1.3.6.1.4.1.232.165.11.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, @@ -325,8 +327,8 @@ static snmp_info_t hpe_pdu3_cis_mib[] = { { "unmapped.pdu3InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.11.2.1.1.7.1", NULL, SU_FLAG_OK, NULL }, /* pdu3InputResettableEnergy.1 = INTEGER: 0 */ { "unmapped.pdu3InputResettableEnergy", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.8.1", NULL, SU_FLAG_OK, NULL }, -/* pdu3InputPowerFactor.1 = INTEGER: 97 */ -{ "unmapped.pdu3InputPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.9.1", NULL, SU_FLAG_OK, NULL }, + /* pdu3InputPowerFactor.1 = INTEGER: 97 */ + { "unmapped.pdu3InputPowerFactor", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.9.1", NULL, SU_FLAG_OK, NULL }, /* pdu3InputPowerVAR.1 = INTEGER: 197 */ { "unmapped.pdu3InputPowerVAR", 0, 1, ".1.3.6.1.4.1.232.165.11.2.1.1.10.1", NULL, SU_FLAG_OK, NULL }, /* pdu3InputPhaseIndex.1.1 = INTEGER: 1 */ @@ -1724,7 +1726,7 @@ static snmp_info_t hpe_pdu3_cis_mib[] = { /* pdu3OutletControlShutoffDelay.1.%i = INTEGER: 0 */ { "unmapped.pdu3OutletControlShutoffDelay", 0, 1, ".1.3.6.1.4.1.232.165.11.5.2.1.9.1.%i", NULL, SU_FLAG_OK, NULL }, -#endif /* WITH_UNMAPPED_DATA_POINTS */ +#endif /* WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/huawei-mib.c b/drivers/huawei-mib.c index 9ff193b7fa..42b90e5845 100644 --- a/drivers/huawei-mib.c +++ b/drivers/huawei-mib.c @@ -232,9 +232,9 @@ static snmp_info_t huawei_mib[] = { { "battery.charge", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.6.100.1.3.1", NULL, SU_FLAG_OK, NULL }, { "battery.runtime", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.6.100.1.4.1", NULL, SU_FLAG_OK, NULL }, - - /* { "unmapped.hwUpsBattTest", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.103.101.1.6.1", NULL, SU_FLAG_OK, NULL }, */ - +#if WITH_UNMAPPED_DATA_POINTS + { "unmapped.hwUpsBattTest", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.103.101.1.6.1", NULL, SU_FLAG_OK, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/raritan-px2-mib.c b/drivers/raritan-px2-mib.c index 5f7ca2d8e2..627105162e 100644 --- a/drivers/raritan-px2-mib.c +++ b/drivers/raritan-px2-mib.c @@ -165,11 +165,12 @@ static snmp_info_t raritan_px2_mib[] = { { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", "1", SU_TYPE_CMD | SU_OUTLET, NULL }, { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", "2", SU_TYPE_CMD | SU_OUTLET, NULL }, -#ifdef DEBUG +#if WITH_UNMAPPED_DATA_POINTS || (defined DEBUG) /* pduCount.0 = INTEGER: 1 */ /* FIXME: part of daisychain support, RFC device.count */ { "device.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.1.0", NULL, SU_FLAG_OK, NULL }, +#if WITH_UNMAPPED_DATA_POINTS /* pduRatedVoltage.1 = STRING: 100-120V */ { "unmapped.pduRatedVoltage", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* pduRatedCurrent.1 = STRING: 16A */ @@ -406,7 +407,7 @@ static snmp_info_t raritan_px2_mib[] = { /* inletSensorStateChangeDelay.1.1.activeEnergy = Gauge32: 0 */ { "unmapped.inletSensorStateChangeDelay", 0, 1, ".1.3.6.1.4.1.13742.6.3.3.4.1.14.1.1.8", NULL, SU_FLAG_OK, NULL }, -/* Inlet thresholds */ + /* Inlet thresholds */ /* inletSensorLowerCriticalThreshold.1.1.rmsCurrent = Gauge32: 0 */ { "unmapped.inletSensorLowerCriticalThreshold", 0, 1, ".1.3.6.1.4.1.13742.6.3.3.4.1.21.1.1.1", NULL, SU_FLAG_OK, NULL }, /* inletSensorLowerCriticalThreshold.1.1.rmsVoltage = Gauge32: 94 */ @@ -577,7 +578,8 @@ static snmp_info_t raritan_px2_mib[] = { * the rest is 18MB of verbose log and satellite data */ /* Note: All reliabilityXXX data were removed */ -#endif /* DEBUG */ +#endif /* WITH_UNMAPPED_DATA_POINTS */ +#endif /* DEBUG || WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } From 1deab1638322e9e64a0cf3200dadc93dbe3a3f41 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 21:36:44 +0100 Subject: [PATCH 0193/1232] drivers/*-hid.c: fence WITH_UNMAPPED_DATA_POINTS [#1699] --- drivers/belkin-hid.c | 4 ++-- drivers/cps-hid.c | 14 ++++++------ drivers/ever-hid.c | 4 +++- drivers/idowell-hid.c | 4 ++-- drivers/liebert-hid.c | 4 ++-- drivers/powercom-hid.c | 48 +++++++++++++++++++++++++++-------------- drivers/tripplite-hid.c | 4 ++-- 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/drivers/belkin-hid.c b/drivers/belkin-hid.c index c1aaccf1eb..686dc92612 100644 --- a/drivers/belkin-hid.c +++ b/drivers/belkin-hid.c @@ -529,7 +529,7 @@ static hid_info_t belkin_hid2nut[] = { yet implemented) workaround, see the belkinunv(8) man page. -PS 2005/08/28 */ -#if 0 +#if WITH_UNMAPPED_DATA_POINTS /* added for debugging Liebert GXT3 : */ { "unmapped.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.imanufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%.0f", 0, NULL }, @@ -543,7 +543,7 @@ static hid_info_t belkin_hid2nut[] = { { "unmapped.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%.0f", 0, NULL }, -#endif +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, NULL, 0, NULL } diff --git a/drivers/cps-hid.c b/drivers/cps-hid.c index aa05794b17..9ae9b65862 100644 --- a/drivers/cps-hid.c +++ b/drivers/cps-hid.c @@ -164,12 +164,14 @@ static usage_tables_t cps_utab[] = { /* --------------------------------------------------------------- */ static hid_info_t cps_hid2nut[] = { - /* { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, */ - /* { "unmapped.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", 0, NULL }, */ - /* { "unmapped.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, */ - /* { "unmapped.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL }, */ - /* { "unmapped.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", 0, NULL }, */ - /* { "unmapped.ups.powersummary.fullchargecapacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.fullchargecapacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* Battery page */ { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion }, diff --git a/drivers/ever-hid.c b/drivers/ever-hid.c index 9f6a674571..609b18076a 100644 --- a/drivers/ever-hid.c +++ b/drivers/ever-hid.c @@ -687,8 +687,10 @@ static hid_info_t ever_hid2nut[] = { /* WAS: experimental.powersummary.delay_before_shutdown */ { "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL }, +#if WITH_UNMAPPED_DATA_POINTS /* not implemented*/ - /* { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, */ + { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.AwaitingPower", NULL, NULL, HU_FLAG_QUICK_POLL, awaitingpower_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BatteryPresent", NULL, NULL, 0, nobattery_info }, diff --git a/drivers/idowell-hid.c b/drivers/idowell-hid.c index f96958f72f..e20505d2dc 100644 --- a/drivers/idowell-hid.c +++ b/drivers/idowell-hid.c @@ -65,7 +65,7 @@ static usage_tables_t idowell_utab[] = { /* --------------------------------------------------------------- */ static hid_info_t idowell_hid2nut[] = { -#ifdef DEBUG +#if WITH_UNMAPPED_DATA_POINTS || (defined DEBUG) { "unmapped.ups.flow.[4].flowid", 0, 0, "UPS.Flow.[4].FlowID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powerconverter.output.outputid", 0, 0, "UPS.PowerConverter.Output.OutputID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powerconverter.powerconverterid", 0, 0, "UPS.PowerConverter.PowerConverterID", NULL, "%.0f", 0, NULL }, @@ -78,7 +78,7 @@ static hid_info_t idowell_hid2nut[] = { { "unmapped.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.presentstatus.undefined", 0, 0, "UPS.PowerSummary.PresentStatus.Undefined", NULL, "%.0f", 0, NULL }, -#endif /* DEBUG */ +#endif /* if WITH_UNMAPPED_DATA_POINTS || DEBUG */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info }, diff --git a/drivers/liebert-hid.c b/drivers/liebert-hid.c index 23851d8850..1ec525286e 100644 --- a/drivers/liebert-hid.c +++ b/drivers/liebert-hid.c @@ -68,7 +68,7 @@ static usage_tables_t liebert_utab[] = { static hid_info_t liebert_hid2nut[] = { -#if 0 +#if WITH_UNMAPPED_DATA_POINTS { "unmapped.ups.powersummary.flowid", 0, 0, "UPS.PowerSummary.FlowID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, @@ -77,7 +77,7 @@ static hid_info_t liebert_hid2nut[] = { { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.imanufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%.0f", 0, NULL }, -#endif +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.2f", 0, NULL }, { "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.2f", HU_FLAG_STATIC, NULL }, diff --git a/drivers/powercom-hid.c b/drivers/powercom-hid.c index 6e4d4a8c8c..5f838e1bc7 100644 --- a/drivers/powercom-hid.c +++ b/drivers/powercom-hid.c @@ -373,19 +373,23 @@ static hid_info_t powercom_hid2nut[] = { { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, { "battery.mfr.date", 0, 0, "UPS.Battery.ManufacturerDate", NULL, "%s", HU_FLAG_STATIC, date_conversion }, { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, -/* { "unmapped.ups.battery.delaybeforestartup", 0, 0, "UPS.Battery.DelayBeforeStartup", NULL, "%.0f", 0, NULL }, */ -/* { "unmapped.ups.battery.initialized", 0, 0, "UPS.Battery.Initialized", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "unmapped.ups.battery.delaybeforestartup", 0, 0, "UPS.Battery.DelayBeforeStartup", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.battery.initialized", 0, 0, "UPS.Battery.Initialized", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", 0, powercom_beeper_info }, { "ups.beeper.status", 0, 0, "UPS.AudibleAlarmControl", NULL, "%s", 0, powercom_beeper_info }, { "ups.load", 0, 0, "UPS.Output.PercentLoad", NULL, "%.0f", 0, NULL }, { "ups.date", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", HU_FLAG_STATIC, date_conversion }, { "ups.test.result", 0, 0, "UPS.Battery.Test", NULL, "%s", 0, test_read_info }, -/* { "unmapped.ups.powersummary.imanufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, */ -/* { "unmapped.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, */ -/* { "unmapped.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, */ -/* { "unmapped.ups.iname", 0, 0, "UPS.iName", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, */ -/* { "unmapped.ups.powersummary.ioeminformation", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "unmapped.ups.powersummary.imanufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, + { "unmapped.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, + { "unmapped.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, + { "unmapped.ups.iname", 0, 0, "UPS.iName", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, + { "unmapped.ups.powersummary.ioeminformation", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* The implementation of the HID path UPS.PowerSummary.DelayBeforeStartup is unconventional: * Read: @@ -423,10 +427,12 @@ static hid_info_t powercom_hid2nut[] = { { "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL }, { "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.1f", 0, NULL }, -/* { "unmapped.ups.powercom1", 0, 0, "UPS.POWERCOM1", NULL, "%.0f", 0, NULL }, broken pipe */ -/* { "unmapped.ups.powercom2", 0, 0, "UPS.POWERCOM2", NULL, "%.0f", 0, NULL }, broken pipe */ -/* { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, */ -/* { "unmapped.ups.shutdownimminent", 0, 0, "UPS.ShutdownImminent", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "unmapped.ups.powercom1", 0, 0, "UPS.POWERCOM1", NULL, "%.0f", 0, NULL }, /* broken pipe */ + { "unmapped.ups.powercom2", 0, 0, "UPS.POWERCOM2", NULL, "%.0f", 0, NULL }, /* broken pipe */ + { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.shutdownimminent", 0, 0, "UPS.ShutdownImminent", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ /* instcmds */ { "beeper.toggle", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL }, @@ -443,12 +449,16 @@ static hid_info_t powercom_hid2nut[] = { { "ups.serial", 0, 0, "PowercomUPS.PowercomSerialNumber", NULL, "%s", 0, stringid_conversion }, { "ups.mfr", 0, 0, "PowercomUPS.PowercomManufacturerName", NULL, "%s", 0, stringid_conversion }, -/* { "UPS.DesignCapacity", 0, 0, "PowercomUPS.PowercomDesignCapacity", NULL, "%.0f", 0, NULL }, is always 255 */ +#if WITH_UNMAPPED_DATA_POINTS + { "UPS.DesignCapacity", 0, 0, "PowercomUPS.PowercomDesignCapacity", NULL, "%.0f", 0, NULL }, /* is always 255 */ +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "ups.mfr.date", 0, 0, "PowercomUPS.PowercomManufacturerDate", NULL, "%s", 0, date_conversion }, { "battery.temperature", 0, 0, "PowercomUPS.PowercomBatterySystem.PowercomTemperature", NULL, "%.0f", 0, NULL }, { "battery.temperature", 0, 0, "UPS.Battery.Temperature", NULL, "%.1f", 0, NULL }, { "battery.charge", 0, 0, "PowercomUPS.PowercomBatterySystem.PowercomVoltage", NULL, "%.0f", 0, NULL }, -/* { "UPS.BatterySystem.SpecificationInfo", 0, 0, "PowercomUPS.PowercomBatterySystem.PowercomSpecificationInfo", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "UPS.BatterySystem.SpecificationInfo", 0, 0, "PowercomUPS.PowercomBatterySystem.PowercomSpecificationInfo", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "input.frequency", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomInput.PowercomFrequency", NULL, "%.0f", 0, NULL }, { "input.voltage", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomInput.PowercomVoltage", NULL, "%.0f", 0, powercom_voltage_conversion }, { "output.voltage", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomVoltage", NULL, "%.0f", 0, powercom_voltage_conversion }, @@ -463,7 +473,9 @@ static hid_info_t powercom_hid2nut[] = { * bit 6 Disable NO LOAD SHUTDOWN (1 = ACTIVE) * bit 7 0 */ -/* { "UPS.PowerConverter.Output.InternalChargeController", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomInternalChargeController", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "UPS.PowerConverter.Output.InternalChargeController", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomInternalChargeController", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomInternalChargeController", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_upsfail_conversion }, { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomInternalChargeController", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_replacebatt_conversion }, { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomInternalChargeController", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_test_conversion }, @@ -478,7 +490,9 @@ static hid_info_t powercom_hid2nut[] = { * bit 6 X * bit 7 SD mode display */ -/* { "UPS.PowerConverter.Output.PrimaryBatterySupport", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomPrimaryBatterySupport", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "UPS.PowerConverter.Output.PrimaryBatterySupport", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomPrimaryBatterySupport", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomPrimaryBatterySupport", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_online_conversion }, /* Low battery status may not work */ { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomPrimaryBatterySupport", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_lowbatt_conversion }, @@ -487,7 +501,9 @@ static hid_info_t powercom_hid2nut[] = { { "BOOL", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomPrimaryBatterySupport", NULL, NULL, HU_FLAG_QUICK_POLL, powercom_overload_conversion }, { "output.frequency", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomOutput.PowercomFrequency", NULL, "%.0f", 0, NULL }, { "ups.test.result", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomTest", NULL, "%s", 0, test_read_info }, -/* { "UPS.PowerConverter.ShutdownRequested", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomShutdownRequested", NULL, "%.0f", 0, NULL }, */ +#if WITH_UNMAPPED_DATA_POINTS + { "UPS.PowerConverter.ShutdownRequested", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomShutdownRequested", NULL, "%.0f", 0, NULL }, +#endif /* if WITH_UNMAPPED_DATA_POINTS */ { "ups.delay.shutdown", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomDelayBeforeShutdown", NULL, "%.0f", 0, NULL }, { "ups.delay.start", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomDelayBeforeStartup", NULL, "%.0f", 0, NULL }, { "load.off", 0, 0, "PowercomUPS.PowercomPowerConverter.PowercomDelayBeforeShutdown", NULL, "0", HU_TYPE_CMD, NULL }, diff --git a/drivers/tripplite-hid.c b/drivers/tripplite-hid.c index 20d51526a2..f661401362 100644 --- a/drivers/tripplite-hid.c +++ b/drivers/tripplite-hid.c @@ -299,7 +299,7 @@ static usage_tables_t tripplite_utab[] = { /* HID2NUT lookup table */ static hid_info_t tripplite_hid2nut[] = { -#ifdef USBHID_UPS_TRIPPLITE_DEBUG +#if WITH_UNMAPPED_DATA_POINTS || (defined USBHID_UPS_TRIPPLITE_DEBUG) /* unmapped variables - meaning unknown */ { "UPS.Flow.0xffff0097", 0, 0, "UPS.Flow.0xffff0097", NULL, "%.0f", 0, NULL }, @@ -340,7 +340,7 @@ static hid_info_t tripplite_hid2nut[] = { { "UPS.OutletSystem.Outlet.0xffff00ac", 0, 0, "UPS.OutletSystem.Outlet.0xffff00ac", NULL, "%.0f", 0, NULL }, { "UPS.PowerSummary.iOEMInformation", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, -#endif /* USBHID_UPS_TRIPPLITE_DEBUG */ +#endif /* if WITH_UNMAPPED_DATA_POINTS || USBHID_UPS_TRIPPLITE_DEBUG */ /* Device page */ { "device.part", 0, 0, "UPS.TLCustom.[1].iUPSPartNumber", NULL, "%s", HU_FLAG_STATIC, stringid_conversion }, From 09a1301bbc0d78cb7e776f4abba9a1b2163c5404 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 16:25:16 +0100 Subject: [PATCH 0194/1232] tools/gitlog2changelog.py: support Python 3.6 (and older 3.x) regarding UTF-8 content of git changelog --- tools/gitlog2changelog.py.in | 44 +++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 5d882cbe37..fe0e9103b9 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -6,17 +6,41 @@ import string, re, os from textwrap import TextWrapper import sys +import subprocess -rev_range = '' +rev_range = 'HEAD' if len(sys.argv) > 1: base = sys.argv[1] rev_range = '%s..HEAD' % base # Execute git log with the desired command line options. -fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') +# Support Python2 and Python3 (esp. 3.6 and earlier) semantics +# with regard to utf-8 content support (avois ascii decoding in Py3) +fin_mode = 0 +# Remove trailing end of line? spitlines() in py3 variant takes care of them +fin_chop = 0 +try: + p = subprocess.Popen( + ['git', 'log', '--summary', '--stat', '--no-merges', '--date=short', ('%s' % rev_range)], + encoding='utf-8', close_fds = True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + fin, ferr = p.communicate() + if p.wait() != 0: + print ("ERROR getting git changelog") + system.exit(1) + fin = fin.splitlines() + fin_mode = 3 +except TypeError: + fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') + fin_mode = 2 + fin_chop = 1 + # Create a ChangeLog file in the current directory. -fout = open('ChangeLog', 'w') +if fin_mode == 3: + fout = open('ChangeLog', 'w', encoding='UTF-8') +else: + fout = open('ChangeLog', 'w') # Set up the loop variables in order to locate the blocks we want authorFound = False @@ -49,7 +73,7 @@ for line in fin: authorList = re.split(': ', line, 1) try: author = authorList[1] - author = author[0:len(author)-1] + author = author[0:len(author) - fin_chop] authorFound = True except: print ("Could not parse authorList = '%s'" % (line)) @@ -59,7 +83,7 @@ for line in fin: dateList = re.split(': ', line, 1) try: date = dateList[1] - date = date[0:len(date)-1] + date = date[0:len(date) - fin_chop] dateFound = True except: print ("Could not parse dateList = '%s'" % (line)) @@ -75,12 +99,12 @@ for line in fin: # Extract the actual commit message for this commit elif authorFound & dateFound & messageFound == False: # Find the commit message if we can - if len(line) == 1: + if len(line) == fin_chop: if messageNL: messageFound = True else: messageNL = True - elif len(line) == 4: + elif len(line) == 3 + fin_chop: messageFound = True else: if len(message) == 0: @@ -129,5 +153,9 @@ for line in fin: prevAuthorLine = authorLine # Close the input and output lines now that we are finished. -fin.close() +if fin_mode == 3: + p.stdout.close() + p.stderr.close() +else: + fin.close() fout.close() From bbab3c36b2217222cc1445ddebc0e38a38c6ab8e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 25 Dec 2022 16:25:53 +0100 Subject: [PATCH 0195/1232] tools/gitlog2changelog.py: avoid prefixing file list to messages whose commit comment starts with equivalent list --- tools/gitlog2changelog.py.in | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index fe0e9103b9..dfdf2fb403 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -137,7 +137,23 @@ for line in fin: # Assemble the actual commit message line(s) and limit the line length # to 80 characters. - commitLine = "* " + files + ": " + message + # Avoid printing same (or equivalen) filename lists twice, if commit + # message starts with them. + if message.startswith(files + ":"): + commitLine = "* " + message + else: + namesF = None + namesM = None + try: + namesM = sorted(re.split(r'[ ,]', message.split(":")[0])) + namesF = sorted(re.split(r'[ ,]', files)) + except: + pass + + if namesM is not None and namesM == namesF: + commitLine = "* " + message + else: + commitLine = "* " + files + ": " + message # Write out the commit line fout.write(wrapper.fill(commitLine) + "\n") From 55f62dc1de48afe6e99922562200dcc5e1c2ca84 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Dec 2022 07:31:24 +0100 Subject: [PATCH 0196/1232] tests/NIT/nit.sh: avoid "sed -i" - safer approach [#1736] --- tests/NIT/nit.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index f589c781e4..cda96d93c4 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -509,9 +509,8 @@ EOF # Avoid "sed -i", it behaves differently on some platforms # and is completely absent on others [#1736 and earlier] for F in "$NUT_CONFPATH/"*.dev "$NUT_CONFPATH/"*.seq ; do - sed -e 's,^ups.status: *$,ups.status: OL BOOST,' < "$F" > "$F.bak" - cat "$F.bak" > "$F" - rm -f "$F.bak" + sed -e 's,^ups.status: *$,ups.status: OL BOOST,' "$F" > "$F.bak" + mv -f "$F.bak" "$F" grep -E '^ups.status:' "$F" >/dev/null || { echo "ups.status: OL BOOST" >> "$F"; } done fi From 940710a5e679fa75e59bb5093da2ff6f6e4adde9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Dec 2022 16:02:22 +0100 Subject: [PATCH 0197/1232] size_t --- include/common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/common.h b/include/common.h index e0aaed549b..6e22e3159d 100644 --- a/include/common.h +++ b/include/common.h @@ -380,6 +380,10 @@ char * getfullpath(char * relative_path); int __cdecl usleep(useconds_t useconds); #endif /* HAVE_USLEEP */ +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t maxlen); +#endif + /* Not all platforms support the flag; this method abstracts * its use (or not) to simplify calls in the actual codebase */ /* TODO: Extend for TYPE_FD and WIN32 eventually? */ From 2fea403819804f7e429c99cb37e25ab2b2c889cf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Dec 2022 16:13:35 +0100 Subject: [PATCH 0198/1232] m4/nut_check_python.m4: recognize python-3.6 too --- m4/nut_check_python.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 9a13513d37..f9680a1fa3 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -137,7 +137,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], PYTHON3="" PYTHON3_SITE_PACKAGES="" AS_CASE([${nut_with_python3}], - [auto|yes|""], [AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.5 python-3.5 python], [_python3_runtime])], + [auto|yes|""], [AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime])], [no], [PYTHON3="no"], [PYTHON3="${nut_with_python3}"] ) From 118fa438052beada907426a12b27deb50da37f18 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Dec 2022 16:28:13 +0100 Subject: [PATCH 0199/1232] configure.ac: if default "python" was not found, use py2 or py3; avoid keeping "no" as an answer [#1736] --- configure.ac | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/configure.ac b/configure.ac index da70360be2..182f4dd066 100644 --- a/configure.ac +++ b/configure.ac @@ -770,6 +770,19 @@ dnl to embed into scripts and Make rules NUT_CHECK_PYTHON NUT_CHECK_PYTHON2 NUT_CHECK_PYTHON3 +AS_IF([test x"$PYTHON2" = xno], [PYTHON2=""]) +AS_IF([test x"$PYTHON3" = xno], [PYTHON3=""]) +AS_IF([test x"$PYTHON" = xno], [PYTHON=""]) +AS_IF([test x"$PYTHON" = x], [ + AC_MSG_CHECKING([which python version to use by default]) + dnl Last hit wins (py3) + AS_IF([test x"$PYTHON2" != x], [PYTHON="$PYTHON2"]) + AS_IF([test x"$PYTHON3" != x], [PYTHON="$PYTHON3"]) + AS_IF([test x"$PYTHON" = x], + [AC_MSG_RESULT([none])], + [AC_MSG_RESULT([$PYTHON])] + ) + ]) dnl ---------------------------------------------------------------------- dnl check for --with-drivers=all (or --with-drivers=name[,name...]) flag From 9cdebcbfd36b290ae30210a3a415d68ad7a69d31 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Dec 2022 16:44:54 +0100 Subject: [PATCH 0200/1232] scripts/augeas/Makefile.am: clean away nutupsconf.aug.in.AUTOGEN_WITHOUT if it appears --- scripts/augeas/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/augeas/Makefile.am b/scripts/augeas/Makefile.am index c24611d06d..247a68e58d 100644 --- a/scripts/augeas/Makefile.am +++ b/scripts/augeas/Makefile.am @@ -44,6 +44,6 @@ CLEANFILES = *-spellchecked DISTCLEANFILES = gen-nutupsconf-aug.py # Generated by autogen.sh and needed to run the configure script: -MAINTAINERCLEANFILES += nutupsconf.aug.in +MAINTAINERCLEANFILES += nutupsconf.aug.in nutupsconf.aug.in.AUTOGEN_WITHOUT DISTCLEANFILES += *.aug From 2f4d53bb3d114227c1049ae3430801c47398436f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Dec 2022 13:17:29 +0000 Subject: [PATCH 0201/1232] ci_build.sh: report PATH and CCACHE decisions in build host settings --- ci_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index 726e9de0f3..1c32a14e10 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -732,7 +732,7 @@ fi echo "Processing BUILD_TYPE='${BUILD_TYPE}' ..." echo "Build host settings:" -set | grep -E '^(CI_.*|OS_*|CANBUILD_.*|NODE_LABELS|MAKE|C.*FLAGS|LDFLAGS|ARCH.*|BITS.*|CC|CXX|CPP|DO_.*|BUILD_.*)=' || true +set | grep -E '^(PATH|.*CCACHE.*|CI_.*|OS_.*|CANBUILD_.*|NODE_LABELS|MAKE|C.*FLAGS|LDFLAGS|ARCH.*|BITS.*|CC|CXX|CPP|DO_.*|BUILD_.*)=' || true uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true if command -v xxd >/dev/null ; then xxd -c 1 -l 6 | tail -1; else if command -v od >/dev/null; then od -N 1 -j 5 -b | head -1 ; else hexdump -s 5 -n 1 -C | head -1; fi; fi < /bin/ls 2>/dev/null | awk '($2 == 1){print "Endianness: LE"}; ($2 == 2){print "Endianness: BE"}' || true From 6e134e9e9685e06552eb7b7e340a2a197c5d4c3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Dec 2022 13:17:54 +0000 Subject: [PATCH 0202/1232] ci_build.sh: cosmetic fix --- ci_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index 1c32a14e10..5d2bc1ceaf 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -779,7 +779,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp else if [ -n "${CI_CCACHE_SYMLINKDIR}" ]; then # Tell ccache the PATH without itself in it, to avoid loops processing - PATH="`echo "$PATH" | sed -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?$,,' -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?$,,'`" + PATH="`echo "$PATH" | sed -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?$,,' -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?$,,'`" fi CCACHE_PATH="$PATH" CCACHE_DIR="${HOME}/.ccache" From b9f08a686a2cfa22715c183a976e927a6b23bfea Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Dec 2022 13:18:45 +0000 Subject: [PATCH 0203/1232] ci_build.sh: apply CCACHE PATH discovery to mingw builds --- ci_build.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 5d2bc1ceaf..145986d8e8 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1849,6 +1849,20 @@ bindings) cross-windows-mingw*) echo "INFO: When using build-mingw-nut.sh consider 'export INSTALL_WIN_BUNDLE=true' to use mainstream DLL co-bundling recipe" >&2 + if [ "$HAVE_CCACHE" = yes ] \ + && [ -n "${CI_CCACHE_SYMLINKDIR}" ] \ + && [ -d "${CI_CCACHE_SYMLINKDIR}" ] \ + ; then + PATH="`echo "$PATH" | sed -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?:,,' -e 's,:'"${CI_CCACHE_SYMLINKDIR}"'/?$,,' -e 's,^'"${CI_CCACHE_SYMLINKDIR}"'/?$,,'`" + CCACHE_PATH="$PATH" + CCACHE_DIR="${HOME}/.ccache" + if (command -v ccache || which ccache) && ls -la "${CI_CCACHE_SYMLINKDIR}" && mkdir -p "${CCACHE_DIR}"/ ; then + echo "INFO: Using ccache via PATH preferring tool names in ${CI_CCACHE_SYMLINKDIR}" >&2 + PATH="${CI_CCACHE_SYMLINKDIR}:$PATH" + export CCACHE_PATH CCACHE_DIR PATH + fi + fi + ./autogen.sh || exit cd scripts/Windows || exit From f9b39326bbc7ccfd6c87925c7c0c3d9cf270eabd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Dec 2022 13:23:28 +0000 Subject: [PATCH 0204/1232] tests/NIT/nit.sh: testcase_upsd_allow_no_device(): give VERY laggy systems (e.g. build farm swapping) another chance --- tests/NIT/nit.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0883f95369..2c15597d06 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -611,6 +611,11 @@ testcase_upsd_allow_no_device() { sleep 3 runcmd upsc -l localhost:$NUT_PORT fi + if echo "$CMDERR" | grep "Error: Server disconnected" >/dev/null ; then + log_warn "Retry once more to rule out very laggy systems" + sleep 15 + runcmd upsc -l localhost:$NUT_PORT + fi [ "$CMDRES" = 0 ] || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" fi if [ -n "$CMDOUT" ] ; then From 89de69b2c607813c77004f69240a4037b04ae843 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 10:30:44 +0100 Subject: [PATCH 0205/1232] tools/nut-scanner/nutscan-init.c: annotate blocks for shared library detection --- tools/nut-scanner/nutscan-init.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 6081e23136..87a78a7502 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -147,9 +147,10 @@ void nutscan_init(void) # ifdef HAVE_PTHREAD_TRYJOIN pthread_mutex_init(&threadcount_mutex, NULL); # endif -#endif /* HAVE_PTHREAD */ +#endif /* HAVE_PTHREAD */ char *libname = NULL; + #ifdef WITH_USB #if WITH_LIBUSB_1_0 libname = get_libname("libusb-1.0" SOEXT); @@ -186,7 +187,8 @@ void nutscan_init(void) nutscan_avail_usb = nutscan_load_usb_library("libusb" SOEXT); } } -#endif +#endif /* WITH_USB */ + #ifdef WITH_SNMP libname = get_libname("libnetsnmp" SOEXT); if (libname) { @@ -196,7 +198,8 @@ void nutscan_init(void) /* let libtool (lt_dlopen) do its default magic maybe better */ nutscan_avail_snmp = nutscan_load_snmp_library("libnetsnmp" SOEXT); } -#endif +#endif /* WITH_SNMP */ + #ifdef WITH_NEON libname = get_libname("libneon" SOEXT); if (!libname) { @@ -212,7 +215,8 @@ void nutscan_init(void) nutscan_avail_xml_http = nutscan_load_neon_library("libneon-gnutls" SOEXT); } } -#endif +#endif /* WITH_NEON */ + #ifdef WITH_AVAHI libname = get_libname("libavahi-client" SOEXT); if (libname) { @@ -222,7 +226,8 @@ void nutscan_init(void) /* let libtool (lt_dlopen) do its default magic maybe better */ nutscan_avail_avahi = nutscan_load_avahi_library("libavahi-client" SOEXT); } -#endif +#endif /* WITH_AVAHI */ + #ifdef WITH_FREEIPMI libname = get_libname("libfreeipmi" SOEXT); if (libname) { @@ -232,7 +237,9 @@ void nutscan_init(void) /* let libtool (lt_dlopen) do its default magic maybe better */ nutscan_avail_ipmi = nutscan_load_ipmi_library("libfreeipmi" SOEXT); } -#endif +#endif /* WITH_FREEIPMI */ + +/* start of libupsclient for "old NUT" (vs. Avahi) protocol - unconditional */ libname = get_libname("libupsclient" SOEXT); #ifdef WIN32 /* TODO: Detect DLL name at build time, or rename it at install time? */ @@ -259,6 +266,8 @@ void nutscan_init(void) } #endif } +/* end of libupsclient for "old NUT" (vs. Avahi) protocol */ + } void nutscan_free(void) From 10025463631acfb304b9225b3b6a2243f95a6d0d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 10:35:21 +0100 Subject: [PATCH 0206/1232] tools/nut-scanner/nutscan-init.c: adjust WIN32 shared library detection for SNMP and NEON [#1735] At least as of Appveyor CI builds and their DLL naming both on MSYS2 MinGW "semi-native" builds, and linux mingw (libneon). --- tools/nut-scanner/nutscan-init.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 87a78a7502..68c2de8350 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -197,6 +197,11 @@ void nutscan_init(void) } else { /* let libtool (lt_dlopen) do its default magic maybe better */ nutscan_avail_snmp = nutscan_load_snmp_library("libnetsnmp" SOEXT); +#ifdef WIN32 + if (!nutscan_avail_snmp) { + nutscan_avail_snmp = nutscan_load_snmp_library("libnetsnmp-40" SOEXT); + } +#endif } #endif /* WITH_SNMP */ @@ -214,6 +219,14 @@ void nutscan_init(void) if (!nutscan_avail_xml_http) { nutscan_avail_xml_http = nutscan_load_neon_library("libneon-gnutls" SOEXT); } +#ifdef WIN32 + if (!nutscan_avail_xml_http) { + nutscan_avail_xml_http = nutscan_load_neon_library("libneon-27" SOEXT); + } + if (!nutscan_avail_xml_http) { + nutscan_avail_xml_http = nutscan_load_neon_library("libneon-gnutls-27" SOEXT); + } +#endif } #endif /* WITH_NEON */ From 506dfa0403f87f018d242bf96a7a5921c88fb3bc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 13:46:22 +0100 Subject: [PATCH 0207/1232] docs/man/upsmon.txt: rearrange paragraphs with related content [#1721] --- docs/man/upsmon.txt | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index c2858b7769..7eb76d9149 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -390,6 +390,23 @@ by starting another copy of the program with `-c fsd` command line argument. This is useful when you want to initiate a shutdown before the critical stage through some external means, such as linkman:upssched[8]. +SIMULATING POWER FAILURES +------------------------- + +To test a synchronized shutdown without pulling the plug on your UPS(es), +you need only set the forced shutdown (FSD) flag on them. You can do this +by calling upsmon again to set the flag, i.e.: + ++upsmon -c fsd+ + +After that, the primary and the secondary will do their usual shutdown +sequence as if the battery had gone critical, while you can time how long +it takes for them. This is much easier on your UPS equipment, and it beats +crawling under a desk to find the plug. + +Note you can also use a dummy SHUTDOWNCMD setting to just report that the +systems would shut down at this point, without actually disrupting their work. + DEAD UPSES ---------- @@ -424,23 +441,6 @@ those values, you *must* stop upsmon and start it back up. upsmon will warn you in the syslog if you make changes to either of those values during a reload. -SIMULATING POWER FAILURES -------------------------- - -To test a synchronized shutdown without pulling the plug on your UPS(es), -you need only set the forced shutdown (FSD) flag on them. You can do this -by calling upsmon again to set the flag, i.e.: - -+upsmon -c fsd+ - -After that, the primary and the secondary will do their usual shutdown -sequence as if the battery had gone critical, while you can time how long -it takes for them. This is much easier on your UPS equipment, and it beats -crawling under a desk to find the plug. - -Note you can also use a dummy SHUTDOWNCMD setting to just report that the -systems would shut down at this point, without actually disrupting their work. - FILES ----- From 3ded6d895aea041b09406284312d4cd2d3309b3b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 13:55:35 +0100 Subject: [PATCH 0208/1232] docs/man/upsmon.txt: clarify that FSD latches until upsd is restarted [#1721] --- docs/man/upsmon.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index 7eb76d9149..313cf2983c 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -390,6 +390,22 @@ by starting another copy of the program with `-c fsd` command line argument. This is useful when you want to initiate a shutdown before the critical stage through some external means, such as linkman:upssched[8]. +WARNING: Please note that by design, since we require power-cycling the +load and don't want some systems to be powered off while others remain +running if the "wall power" returns at the wrong moment as usual, the "FSD" +flag can not be removed from the data server unless its daemon is restarted. +If we do take the first step in critical mode, then we normally intend to go +all the way -- shut down all the servers gracefully, and power down the UPS. + +Keep in mind that some UPS devices and corresponding drivers would also latch +or otherwise resurface the "FSD" state again even if "wall power" is available, +but the remaining battery charge is below a threshold configured as "safe" in +the device (usually if you manually power on the UPS after a long power outage). +This is by design of respective UPS vendors, since in such situation they +can not guarantee that if a new power outage happens, their UPS would safely +shut down your systems again. So it is deemed better and safer to stay dark +until batteries become sufficiently charged. + SIMULATING POWER FAILURES ------------------------- @@ -407,6 +423,11 @@ crawling under a desk to find the plug. Note you can also use a dummy SHUTDOWNCMD setting to just report that the systems would shut down at this point, without actually disrupting their work. +WARNING: after such "dummy" experiments you may have to restart the NUT data +server `upsd` to clear its "FSD" flag for the devices and clients involved, +and make sure no files named by `POWERDOWNFLAG` option (e.g. `/etc/killpower`) +remain on the `upsmon primary` systems under test. + DEAD UPSES ---------- From 00e3a88906cac7f4261f1d746f38db3b5e9fb638 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 14:06:08 +0100 Subject: [PATCH 0209/1232] INSTALL.nut: clarify that the instruction is for tarballs (hint for builds of git checkouts) [#1750] --- INSTALL.nut | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/INSTALL.nut b/INSTALL.nut index c5b2760268..58a0f970b5 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -13,7 +13,15 @@ greatest fixes, new drivers, bugs and other features. Installing from source ---------------------- -These are the essential steps for compiling and installing this software. +These are the essential steps for compiling and installing this software +from distribution archives (usually "release tarballs") which include a +pre-built copy of the `configure` script and some other generated source +files. + +To build NUT from a Git checkout you may need some additional tools +(referenced just a bit below) and run `./autogen.sh` to generate the +needed files. For common developer iterations, porting to new platforms, +or in-place testing, running the `./ci_build.sh` script can be helpful. The NUT linkdoc:packager-guide[Packager Guide], which presents the best practices for installing and integrating NUT, is also a good reading. From 0458171c1851c5e06a89bc0613f6f0b1f070059e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 14:06:43 +0100 Subject: [PATCH 0210/1232] NEWS: Clarified documentation in codebase according to end-user feedback for NUT v2.8.1 release --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 8148c2e476..ee1ec33923 100644 --- a/NEWS +++ b/NEWS @@ -200,6 +200,9 @@ https://github.com/networkupstools/nut/milestone/8 last reported themselves as "stale" (and might later crash) so their connections would be terminated if really no longer active [#1626] + - Clarified documentation in codebase according to end-user feedback [#1721, + #1750 and others over time] + - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, `time_t` etc.) in third-party client code that earlier sufficed to only From ecc6dfa9ad15a4629bfda39a2d35c571e7bbebd0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 14:12:04 +0100 Subject: [PATCH 0211/1232] NEWS: reference arcane installation know-how for Solaris 8 [#1736] --- NEWS | 5 +++++ docs/nut.dict | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ee1ec33923..a7268c1547 100644 --- a/NEWS +++ b/NEWS @@ -172,6 +172,11 @@ https://github.com/networkupstools/nut/milestone/8 - some fixes for builds on older OSes with less functional default system shell interpreters - now `autogen.sh` supports a `CONFIG_SHELL` envvar to inject its value into generated `configure` script [#1736] + * Note that you may have to install additional tools (possibly from + third-party FOSS packaging efforts) to prepare and build the NUT + codebase, and/or prefer non-default system provided implementations + (e.g. to use the XPG4 `grep` with `-E` support on Solaris as detailed + in https://github.com/networkupstools/nut/issues/1736 comments) - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the diff --git a/docs/nut.dict b/docs/nut.dict index 2cfa367b89..5e5b651a6a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3061 utf-8 +personal_ws-1.1 en 3062 utf-8 AAS ABI ACFAIL @@ -1357,6 +1357,7 @@ XOFF XON XOPEN XP +XPG XPPC XSL XT From 72edde7c62bdf5e79d324eb043f8bad8612c4bdc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 16:43:53 +0100 Subject: [PATCH 0212/1232] Rename generated nut-common.tmpfiles(.in) => nut-common-tmpfiles.conf(.in) to install a *.conf pattern [#1754] Follow-up for #1030, #1037, #1117 May be related to #1712 --- autogen.sh | 4 ++-- configure.ac | 12 ++++++------ scripts/systemd/.gitignore | 6 +++--- scripts/systemd/Makefile.am | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/autogen.sh b/autogen.sh index 391c70a0ee..6e9e89cfcb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -84,8 +84,8 @@ then fi fi -if [ ! -f scripts/systemd/nut-common.tmpfiles.in ]; then - echo '# autoconf requires this file exists before generating configure script; it will be overwritten by configure during a build' > scripts/systemd/nut-common.tmpfiles.in +if [ ! -f scripts/systemd/nut-common-tmpfiles.conf.in ]; then + echo '# autoconf requires this file exists before generating configure script; it will be overwritten by configure during a build' > scripts/systemd/nut-common-tmpfiles.conf.in fi # now we can safely call autoreconf diff --git a/configure.ac b/configure.ac index 90a2fcee31..176ad23e29 100644 --- a/configure.ac +++ b/configure.ac @@ -3645,10 +3645,10 @@ ABS_TOP_BUILDDIR="`cd "${TOP_BUILDDIR}" && pwd`" || AC_MSG_ERROR([Can not detect ABS_TOP_SRCDIR="`cd "${abs_srcdir}" && pwd`" || AC_MSG_ERROR([Can not detect ABS_TOP_SRCDIR]) AM_CONDITIONAL([BUILDING_IN_TREE], [test "${ABS_TOP_BUILDDIR}" = "${ABS_TOP_SRCDIR}"]) -AC_MSG_CHECKING([whether to customize ${TOP_BUILDDIR}/scripts/systemd/nut-common.tmpfiles.in for this system]) +AC_MSG_CHECKING([whether to customize ${TOP_BUILDDIR}/scripts/systemd/nut-common-tmpfiles.conf.in for this system]) AS_IF([test -n "$systemdtmpfilesdir"], [mkdir -p "${TOP_BUILDDIR}"/scripts/systemd - cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF + cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF # State file (e.g. upsd to driver) and pidfile location for NUT: d @STATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @STATEPATH@ @@ -3656,19 +3656,19 @@ EOF AS_IF([test "$STATEPATH" != "$PIDPATH"], [AS_CASE(["${PIDPATH}"], [*/run|*/tmp|*/shm], [], dnl Do not intrude into system paths; TODO: add more if appropriate for some Linux distro - [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF + [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF d @PIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @PIDPATH@ EOF ])]) AS_IF([test -n "$ALTPIDPATH" && test "$STATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTPIDPATH"], - [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF + [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF d @ALTPIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @ALTPIDPATH@ EOF]) dnl Generally added to support some forks AS_IF([test -n "$ALTSTATEPATH" && test "$STATEPATH" != "$ALTSTATEPATH" && test "$ALTSTATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTSTATEPATH"], - [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common.tmpfiles.in << EOF + [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF d @ALTSTATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @ALTSTATEPATH@ EOF]) @@ -3716,7 +3716,7 @@ AC_CONFIG_FILES([ scripts/python/module/PyNUT.py scripts/upsdrvsvcctl/Makefile scripts/systemd/Makefile - scripts/systemd/nut-common.tmpfiles + scripts/systemd/nut-common-tmpfiles.conf scripts/systemd/nut-driver@.service scripts/systemd/nut-monitor.service scripts/systemd/nut-server.service diff --git a/scripts/systemd/.gitignore b/scripts/systemd/.gitignore index aca233407d..45a6b841a8 100644 --- a/scripts/systemd/.gitignore +++ b/scripts/systemd/.gitignore @@ -1,6 +1,6 @@ -# Note: nut-common.tmpfiles.in is also generated, by configure script -/nut-common.tmpfiles.in -/nut-common.tmpfiles +# Note: nut-common-tmpfiles.conf.in is also generated, by configure script +/nut-common-tmpfiles.conf.in +/nut-common-tmpfiles.conf /nut-driver.service /nut-driver@.service /nut-driver.target diff --git a/scripts/systemd/Makefile.am b/scripts/systemd/Makefile.am index 8ba1274921..dafdd5ae99 100644 --- a/scripts/systemd/Makefile.am +++ b/scripts/systemd/Makefile.am @@ -12,7 +12,7 @@ systemdsystemunit_DATA = \ nut.target systemdtmpfiles_DATA = \ - nut-common.tmpfiles + nut-common-tmpfiles.conf EXTRA_DIST += nut-driver.target nut.target @@ -28,10 +28,10 @@ EXTRA_DIST += \ nut-server.service.in nutshutdown.in nut-driver.target nut.target \ nut-driver-enumerator.path.in nut-driver-enumerator.service.in -# NOTE: Do not EXTRA_DIST nut-common.tmpfiles.in - it is generated per build +# NOTE: Do not EXTRA_DIST nut-common-tmpfiles.conf.in - it is generated per build endif MAINTAINERCLEANFILES = Makefile.in .dirstamp # Generated by autogen.sh and needed to run the configure script: -MAINTAINERCLEANFILES += nut-common.tmpfiles.in +MAINTAINERCLEANFILES += nut-common-tmpfiles.conf.in From 3179bdec9b1144faaa28a970af0a274eeb283603 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 16:51:45 +0100 Subject: [PATCH 0213/1232] UPGRADING: highlight nut-common.tmpfiles(.in) => nut-common-tmpfiles.conf(.in) rename and other changes since NUT v2.8.0 release --- UPGRADING | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/UPGRADING b/UPGRADING index dc77cd25ec..f3c363258a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -57,6 +57,15 @@ Changes from 2.8.0 to 2.8.1 to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] +- Renamed generated nut-common.tmpfiles(.in) => nut-common-tmpfiles.conf(.in) + to install a /usr/lib/systemd-tmpfiles/*.conf pattern [#1755] + + * If earlier NUT v2.8.0 package recipes for your Linux distribution dealt + with this file, you may have to adjust its name for newer releases. + + * Several other issues have been fixed related to this file and its content, + including #1030, #1037, #1117 and #1712 + - snmp-ups: some subdrivers (addressed using the driver parameter `mibs`) were renamed: `pw` is now `eaton_pw_nm2`, and `pxgx_ups` is `eaton_pxg_ups` [#1715] From 4db205c5d6165cf637189499e7a3a13d6dfaa57f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 18:09:52 +0100 Subject: [PATCH 0214/1232] drivers/upsdrvctl.c, scripts/systemd/nut-driver@.service.in: add support for NUT_IGNORE_NOWAIT [#1753] --- docs/man/ups.conf.txt | 3 +++ docs/man/upsdrvctl.txt | 2 ++ docs/man/upsdrvsvcctl.txt | 2 ++ drivers/upsdrvctl.c | 10 ++++++++-- scripts/systemd/nut-driver@.service.in | 1 + 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index 3de6c5f81d..3416728dfa 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -80,6 +80,9 @@ Optional. Specify to upsdrvctl to not wait at all for the driver(s) to execute the request command. + The default (omission) is to wait. ++ +It can be overridden by `NUT_IGNORE_NOWAIT` environment variable +(e.g. used to work around certain issues with systemd otherwise). *retrydelay*:: Optional. Specify the delay between each restart attempt of the driver(s), diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 46ec658d7c..8bf336e504 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -85,6 +85,8 @@ play around with this option. Only use it when your systems are prepared to lose power. NOTE: refer to linkman:ups.conf[5] for using the *nowait* parameter. +It can be overridden by `NUT_IGNORE_NOWAIT` environment variable +(e.g. used to work around certain issues with systemd otherwise). ENVIRONMENT VARIABLES --------------------- diff --git a/docs/man/upsdrvsvcctl.txt b/docs/man/upsdrvsvcctl.txt index fdace1f9bd..97855851fc 100644 --- a/docs/man/upsdrvsvcctl.txt +++ b/docs/man/upsdrvsvcctl.txt @@ -145,6 +145,8 @@ play around with this option. Only use it when your systems are prepared to lose power. NOTE: refer to linkman:ups.conf[5] for using the *nowait* parameter. +It can be overridden by `NUT_IGNORE_NOWAIT` environment variable +(e.g. used to work around certain issues with systemd otherwise). ENVIRONMENT VARIABLES --------------------- diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 1c6545f141..4bb4e2e3ed 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -90,8 +90,14 @@ void do_upsconf_args(char *upsname, char *var, char *val) if (!strcmp(var, "retrydelay")) retrydelay = atoi(val); - if (!strcmp(var, "nowait")) - waitfordrivers = 0; + if (!strcmp(var, "nowait")) { + char * s = getenv("NUT_IGNORE_NOWAIT"); + if (s && !strcmp(s, "true")) { + upsdebugx(0, "NOTE: 'nowait' setting ignored due to NUT_IGNORE_NOWAIT envvar"); + } else { + waitfordrivers = 0; + } + } /* ignore anything else - it's probably for main */ diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 3f1d028d61..f3e08a4c23 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -38,6 +38,7 @@ PartOf=nut-driver.target # Finally note that "nut-driver-enumerator.service" should take care of this. [Service] +Environment=NUT_IGNORE_NOWAIT=true EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl start "$NUTDEV"' From 3b3773195082a95affab6ec1663c7937b1edce04 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Jan 2023 19:36:28 +0100 Subject: [PATCH 0215/1232] COPYING: update to acknowledge codebase picked up from BSD, curl and CC BY-SA sources over time --- COPYING | 18 ++++++++++++++++++ docs/nut.dict | 7 +++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/COPYING b/COPYING index 883d3b1218..22de43ea47 100644 --- a/COPYING +++ b/COPYING @@ -10,3 +10,21 @@ The Perl client module (scripts/perl/Nut.pm) is released under the same license as Perl itself. That is to say either GPL version 1 or (at your option) any later version, or the "Artistic License". + + Several fallback implementations for methods absent from standard library of + an end-user's current build platform are derived from source code available + under the two-clause BSD license (common/strptime.c, common/strnlen.c) + + Various methods may be adapted from code or ideas posted on Stack Exchange + sites (comments in NUT sources refer to original posts in this case), which + according to https://stackoverflow.com/help/licensing are made available under + different Creative Commons Attribution-ShareAlike license (CC BY-SA) versions + depending on contribution timestamp. + + Several autoconf methods under m4/ directory are derived from curl codebase + and were originally available under curl license. Which is not unlike the MIT + license, see https://daniel.haxx.se/blog/2022/06/17/curl-is-reuse-compliant/ + + To the best of our knowledge, conditions of the 2/3-clause BSD, MIT, curl and + CC BY-SA licenses allow redistribution and reuse of the codebase in projects + made available under GPL license terms, as long as attribution is provided. diff --git a/docs/nut.dict b/docs/nut.dict index 5e5b651a6a..a6ebbf9756 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3062 utf-8 +personal_ws-1.1 en 3067 utf-8 AAS ABI ACFAIL @@ -1131,6 +1131,7 @@ Sequentializing SerialNumber Serv Shara +ShareAlike Shaul ShdnDbnc ShdnDly @@ -2323,9 +2324,9 @@ nitram nl nlb nlogic +nm nn nnn -nm noAuthNoPriv nobody's nobt @@ -2735,6 +2736,8 @@ strdup strerror strftime strlen +strnlen +strptime struct structs sts From cce3cc1a01301fc64a3dee42b5d5645aba52186a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 19:39:16 +0100 Subject: [PATCH 0216/1232] clients/upsmon.c: debug-trace notification activity [#1760] --- clients/upsmon.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index fd9a560516..24db433b32 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -222,11 +222,18 @@ static void notify(const char *notice, int flags, const char *ntype, int ret; #endif - if (flag_isset(flags, NOTIFY_IGNORE)) + upsdebugx(6, "%s: sending notification for [%s]: type %s with flags 0x%04x: %s", + __func__, upsname, ntype, flags, notice); + + if (flag_isset(flags, NOTIFY_IGNORE)) { + upsdebugx(6, "%s: NOTIFY_IGNORE", __func__); return; + } - if (flag_isset(flags, NOTIFY_SYSLOG)) + if (flag_isset(flags, NOTIFY_SYSLOG)) { + upsdebugx(6, "%s: NOTIFY_SYSLOG (as LOG_NOTICE)", __func__); upslogx(LOG_NOTICE, "%s", notice); + } #ifndef WIN32 /* fork here so upsmon doesn't get wedged if the notifier is slow */ @@ -237,16 +244,24 @@ static void notify(const char *notice, int flags, const char *ntype, return; } - if (ret != 0) /* parent */ + if (ret != 0) { /* parent */ + upsdebugx(6, "%s (parent): forked a child to notify via subprocesses", __func__); return; + } /* child continues and does all the work */ + upsdebugx(6, "%s (child): forked to notify via subprocesses", __func__); - if (flag_isset(flags, NOTIFY_WALL)) + if (flag_isset(flags, NOTIFY_WALL)) { + upsdebugx(6, "%s (child): NOTIFY_WALL", __func__); wall(notice); + } if (flag_isset(flags, NOTIFY_EXEC)) { if (notifycmd != NULL) { + upsdebugx(6, "%s (child): NOTIFY_EXEC: calling NOTIFYCMD as '%s \"%s\"'", + __func__, notifycmd, notice); + snprintf(exec, sizeof(exec), "%s \"%s\"", notifycmd, notice); if (upsname) @@ -258,6 +273,8 @@ static void notify(const char *notice, int flags, const char *ntype, if (system(exec) == -1) { upslog_with_errno(LOG_ERR, "%s", __func__); } + } else { + upsdebugx(6, "%s (child): NOTIFY_EXEC: no NOTIFYCMD was configured", __func__); } } From a679e521aabdaf694c5d96e2e2faa960bc8a653b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 21:32:32 +0100 Subject: [PATCH 0217/1232] clients/upsmon.c: "upsmon -K" should not die if daemon is running [#1680] Closes: #1680 --- clients/upsmon.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 24db433b32..f35eabd703 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2432,9 +2432,15 @@ int main(int argc, char *argv[]) if (cmd) { upsdebugx(1, "Signaled old daemon OK"); } else { - printf("Fatal error: A previous upsmon instance is already running!\n"); - printf("Either stop the previous instance first, or use the 'reload' command.\n"); - exit(EXIT_FAILURE); + if (checking_flag) { + printf("Note: A previous upsmon instance is already running!\n"); + printf("Usually it should not be running during OS shutdown,\n"); + printf("which is when checking POWERDOWNFLAG makes most sense.\n"); + } else { + printf("Fatal error: A previous upsmon instance is already running!\n"); + printf("Either stop the previous instance first, or use the 'reload' command.\n"); + exit(EXIT_FAILURE); + } } break; From 8de80f102bb7d103c2ca94e4b0fbf3f41fa9bfc9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 21:40:46 +0100 Subject: [PATCH 0218/1232] clients/upsmon.c: remember debug level specified in command line args, may be useful in reload [#1761] --- clients/upsmon.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/clients/upsmon.c b/clients/upsmon.c index f35eabd703..088344a880 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -115,6 +115,10 @@ static sigset_t nut_upsmon_sigmask; * than that would not have effect, can only have more). */ static int nut_debug_level_global = -1; +/* Debug level specified via command line - we revert to + * it when reloading if there was no DEBUG_MIN in ups.conf + */ +static int nut_debug_level_args = 0; static void setflag(int *val, int flag) { @@ -1628,6 +1632,13 @@ static void loadconfig(void) "Applying debug_min=%d from upsmon.conf", nut_debug_level_global); nut_debug_level = nut_debug_level_global; + } else { + /* DEBUG_MIN is absent or commented-away in ups.conf */ + upslogx(LOG_INFO, + "Applying debug level %d from " + "original command line arguments", + nut_debug_level_args); + nut_debug_level = nut_debug_level_args; } } @@ -2336,6 +2347,7 @@ int main(int argc, char *argv[]) #endif case 'D': nut_debug_level++; + nut_debug_level_args++; break; case 'F': foreground = 1; From ebcff51e495ccc03cfcf1d2cb4ff3304d9041513 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 21:41:04 +0100 Subject: [PATCH 0219/1232] clients/upsmon.c: do not report initial debug level twice --- clients/upsmon.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 088344a880..f0767a5aa1 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2559,10 +2559,6 @@ int main(int argc, char *argv[]) background(); } - if (nut_debug_level >= 1) { - upsdebugx(1, "debug level is '%d'", nut_debug_level); - } - /* only do the pipe stuff if the user hasn't disabled it */ if (use_pipe) { struct passwd *new_uid = get_user_pwent(run_as_user); From a1606be883331d880f34137ec037280723a11807 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 21:48:45 +0100 Subject: [PATCH 0220/1232] server/upsd.c, server/conf.c: remember debug level specified in command line args, may be useful in reload [#1761] Closes: #1761 --- server/conf.c | 11 +++++++++++ server/conf.h | 1 + server/upsd.c | 1 + 3 files changed, 13 insertions(+) diff --git a/server/conf.c b/server/conf.c index 406a60fc96..6086397934 100644 --- a/server/conf.c +++ b/server/conf.c @@ -36,6 +36,10 @@ int num_ups = 0; * than that would not have effect, can only have more). */ int nut_debug_level_global = -1; +/* Debug level specified via command line - we revert to + * it when reloading if there was no DEBUG_MIN in upsd.conf + */ +int nut_debug_level_args = 0; /* add another UPS for monitoring from ups.conf */ static void ups_create(const char *fn, const char *name, const char *desc) @@ -390,6 +394,13 @@ void load_upsdconf(int reloading) "Applying debug_min=%d from upsd.conf", nut_debug_level_global); nut_debug_level = nut_debug_level_global; + } else { + /* DEBUG_MIN is absent or commented-away in ups.conf */ + upslogx(LOG_INFO, + "Applying debug level %d from " + "original command line arguments", + nut_debug_level_args); + nut_debug_level = nut_debug_level_args; } } diff --git a/server/conf.h b/server/conf.h index 432b7f9c3e..46bc5dbadb 100644 --- a/server/conf.h +++ b/server/conf.h @@ -52,6 +52,7 @@ void delete_access(void); extern int num_ups; extern int nut_debug_level_global; +extern int nut_debug_level_args; #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/server/upsd.c b/server/upsd.c index 3c926a53e1..138688bf47 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1651,6 +1651,7 @@ int main(int argc, char **argv) case 'D': nut_debug_level++; + nut_debug_level_args++; break; case 'F': if (foreground > 0) { From 83be8e697f7fb6fc6427c49458521c326cebd80a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 22:22:51 +0100 Subject: [PATCH 0221/1232] configure.ac and many others: make default POWERDOWNFLAG configurable [#529] Closes: #529 --- NEWS | 5 +++++ conf/upsmon.conf.sample.in | 6 ++++-- configure.ac | 38 ++++++++++++++++++++++++++++++++++++++ docs/configure.txt | 7 +++++++ docs/nut.dict | 4 +++- 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index a7268c1547..1d6f5de307 100644 --- a/NEWS +++ b/NEWS @@ -208,6 +208,11 @@ https://github.com/networkupstools/nut/milestone/8 - Clarified documentation in codebase according to end-user feedback [#1721, #1750 and others over time] + - Several fixes for `upsmon` behavior [#1761, #1680...], including new + ability to configure default POWERDOWNFLAG location -- packagers are + encouraged to pick optimal location for their distributions (which + remains mounted at least read-only late in shutdown) [#529] + - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, `time_t` etc.) in third-party client code that earlier sufficed to only diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 8e86e00d0c..9986cc44b0 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -258,8 +258,10 @@ DEADTIME 15 # # For Windows setup use something like: # POWERDOWNFLAG "C:\\killpower" - -POWERDOWNFLAG /etc/killpower +# +# For Unix/Linux systems the legacy default is: +# POWERDOWNFLAG /etc/killpower +POWERDOWNFLAG "@POWERDOWNFLAG@" # -------------------------------------------------------------------------- # NOTIFYMSG - change messages sent by upsmon when certain events occur diff --git a/configure.ac b/configure.ac index 176ad23e29..6ea9cd87d6 100644 --- a/configure.ac +++ b/configure.ac @@ -71,6 +71,13 @@ dnl | default values for things later on (can be overridden) | STATEPATH="/var/state/ups" +dnl NOTE: NUT legacy default, keep as is for least surprise +dnl Distributions are however welcome to specify the option to use tmpfs +AS_CASE([${target_os}], + [*mingw*], [POWERDOWNFLAG="C:\\killpower"], dnl NOTE: Double backslashes are correct! + [POWERDOWNFLAG="/etc/killpower"] dnl POSIX systems default +) + cgiexecdir='${exec_prefix}/cgi-bin' driverexecdir='${exec_prefix}/bin' htmldir='${prefix}/html' @@ -2237,6 +2244,36 @@ AC_ARG_WITH(pidpath, NUT_REPORT_SETTING_PATH([Privileged PID file path], PIDPATH, "${PIDPATH}", [Path for pid files of processes running as root, such as upsmon]) +dnl -------------------------------------------------------------------- +dnl Legacy default was /etc/killpower, but modern distros may prefer some +dnl temporary filesystem (no I/O storage device impact) as long as it is +dnl mounted at least read-only late in shutdown routine. The upsmon program +dnl writes it as root, so this may well be in /var/run or in NUT PID/state +dnl path (if that location remains mounted in run-time OS distribution). +dnl Ideally the filesystems with `upsmon` program and libraries it needs +dnl also remain mounted, so `upsmon -K` may be queried late in shutdown - +dnl and we can avoid hardcoding such paths into those shutdown hooks. +dnl Note that upsmon removes this file early in any daemonized start-up. +AC_MSG_CHECKING(if requested default upsmon POWERDOWNFLAG path) +AC_ARG_WITH(powerdownflag, + AS_HELP_STRING([--with-powerdownflag=PATH], [default path for upsmon POWERDOWNFLAG file (${POWERDOWNFLAG}, typically /etc/killpower)]), +[ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-powerdownflag - see docs/configure.txt) + ;; + *) + POWERDOWNFLAG="${withval}" + AC_MSG_RESULT([specified]) + ;; + esac +], [AC_MSG_RESULT([default])]) +dnl # This should be internal detail for "upsmon -K" implementation, +dnl # so not necessarily reported (reduce noise): +dnl NUT_REPORT_SETTING_PATH([Default upsmon POWERDOWNFLAG path], +dnl POWERDOWNFLAG, "${POWERDOWNFLAG}", [Default path for upsmon POWERDOWNFLAG file]) + +dnl --------------------------------------------------------------------- AC_MSG_CHECKING(if requested driver path) AC_ARG_WITH(drvpath, AS_HELP_STRING([--with-drvpath=PATH], [where to install UPS drivers (EPREFIX/bin)]), @@ -3298,6 +3335,7 @@ AC_SUBST(STATEPATH) AC_SUBST(ALTPIDPATH) dnl #Not in main codebase yet# AC_SUBST(ALTSTATEPATH) AC_SUBST(CONFPATH) +AC_SUBST(POWERDOWNFLAG) AC_SUBST(BINDIR) AC_SUBST(LIBDIR) AC_SUBST(NUT_DATADIR, [`eval echo "${NUT_DATADIR}"`]) diff --git a/docs/configure.txt b/docs/configure.txt index 91c2336db1..488e7225eb 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -570,6 +570,13 @@ to interact with the data server `upsd`. Default is `/var/state/ups`. The `NUT_STATEPATH` environment variable overrides this at run time. + --with-powerdownflag=FILEPATH + +Change the default location (full filename path) of the POWERDOWNFLAG +created by `upsmon` (as `root`) to tell the late-shutdown integration +that this machine should tell all UPSes for which it is a "primary" NUT +server to cut power to the load. Default is `/etc/killpower` on POSIX +systems and `"C:\\killpower"` (note the double backslashes) on Windows. Things the compiler might need to find -------------------------------------- diff --git a/docs/nut.dict b/docs/nut.dict index 5e5b651a6a..e034c7d28c 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3062 utf-8 +personal_ws-1.1 en 3064 utf-8 AAS ABI ACFAIL @@ -340,6 +340,7 @@ FEMEA FFF FH FHS +FILEPATH FINALDELAY FIPS FIXME @@ -2473,6 +2474,7 @@ portname powercom powerdev powerdown +powerdownflag powerfactor powerman powermand From 2868b416b6d4c2c0f1099e94e80e64bc01395be8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 22:42:18 +0100 Subject: [PATCH 0222/1232] docs/FAQ.txt: modernize about "upsmon -K" and POWERDOWNFLAG or explicit /etc/killpower [#529] --- docs/FAQ.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/FAQ.txt b/docs/FAQ.txt index 3c37951881..d8e24baceb 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -310,7 +310,7 @@ might look like this: # `upsmon -K` if available on still mounted filesystems # at this point is more portable than the `test` below - if (test -f /etc/killpower) + if (test -f /etc/killpower || /sbin/upsmon -K) then /sbin/upsdrvctl shutdown @@ -1012,9 +1012,11 @@ Or a variation like... You can rig up a little hack to handle this issue in software. Essentially, you need to test for the POWERDOWNFLAG in your *startup* scripts -while the filesystems are still read-only. If it's there, you know your last -shutdown was caused by a power failure and the UPS battery is probably still -quite weak. +while the filesystems are still read-only (before `upsmon` daemon has started +and removed it). You can also query `upsmon -K` for presence of the file, to +avoid hard-coding the path or parsing it from your `upsmon.conf` file. If the +flag is there, you know your last shutdown was caused by a power failure and +the UPS battery is probably still quite weak. In this situation, your best bet is to sleep it off. Pausing in your startup script to let the batteries recharge with the filesystems in a safe state is @@ -1054,7 +1056,7 @@ Implement this by modifying your shutdown script like this: # `upsmon -K` if available on still mounted filesystems # at this point is more portable than the `test` below - if (test -f /etc/killpower) + if (test -f /etc/killpower || /sbin/upsmon -K) then /sbin/upsdrvctl shutdown From e7e37e90b5dd2e1b819a8e25cfb14db3e487c4c2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Jan 2023 22:45:34 +0100 Subject: [PATCH 0223/1232] docs/man/belkinunv.txt: modernize about "upsmon -K" and POWERDOWNFLAG or explicit /etc/killpower [#529] --- docs/man/belkinunv.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/man/belkinunv.txt b/docs/man/belkinunv.txt index 4d8d8c288f..709eb59536 100644 --- a/docs/man/belkinunv.txt +++ b/docs/man/belkinunv.txt @@ -291,7 +291,7 @@ readable at that point. # NEAR END OF SHUTDOWN SCRIPT: # if shutdown was caused by UPS, perform Belkin UPS workaround. - if [ -f /etc/killpower ] ; then + if [ -f /etc/killpower ] || /usr/sbin/upsmon -K ; then echo "Waiting for AC power, or for UPS batteries to run out..." /usr/bin/belkinunv -x wait /dev/ttyS1 @@ -309,7 +309,7 @@ file system integrity checks are done. # NEAR BEGINNING OF STARTUP SCRIPT: # if we are recovering from a power failure, wait for the UPS to # charge to a comfortable level before writing anything to disk - if [ -f /etc/killpower ] ; then + if [ -f /etc/killpower ] || /usr/sbin/upsmon -K ; then echo "Waiting for UPS battery charge to reach 60%..." /usr/bin/belkinunv -x wait=60 -x nohang /dev/ttyS1 fi From 35a67d4d3b2ed63c6a5549a3970f3336d93e3dd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 01:44:51 +0100 Subject: [PATCH 0224/1232] configure.ac: revise configuration of NUT path location variables and their substitutions --- configure.ac | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 6ea9cd87d6..ee4ef7be41 100644 --- a/configure.ac +++ b/configure.ac @@ -2180,6 +2180,7 @@ AM_CONDITIONAL([HAVE_WINDOWS], [test "${nut_have_mingw_resgen}" = "yes"]) dnl ---------------------------------------------------------------------- +PREFIX="${prefix}" NUT_REPORT_SETTING_PATH([Default installation prefix path], PREFIX, "${prefix}", [Default installation prefix path]) @@ -2291,6 +2292,7 @@ AC_ARG_WITH(drvpath, conftemp="${driverexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" +DRVPATH="${conftemp}" NUT_REPORT_SETTING_PATH([Driver program path], DRVPATH, "${conftemp}", [Default path for UPS drivers]) @@ -2311,6 +2313,7 @@ AC_ARG_WITH(cgipath, conftemp="${cgiexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" +CGIPATH="${conftemp}" NUT_REPORT_SETTING_PATH([CGI program path], CGIPATH, "${conftemp}", [Default path for CGI programs]) @@ -2331,6 +2334,7 @@ AC_ARG_WITH(htmlpath, conftemp="${htmldir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" +HTMLPATH="${conftemp}" NUT_REPORT_SETTING_PATH([HTML file path], HTMLPATH, "${conftemp}", [Default path for HTML files (CGI templates)]) @@ -3092,7 +3096,7 @@ dnl autotools default would be $prefix/etc conftemp="${sysconfdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -CONFPATH=${conftemp} +CONFPATH="${conftemp}" NUT_REPORT_SETTING_PATH([Config file path], CONFPATH, "${conftemp}", [Default path for configuration files]) @@ -3100,7 +3104,7 @@ dnl same for datadir conftemp="${datadir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -NUT_DATADIR=${conftemp} +NUT_DATADIR="${conftemp}" NUT_REPORT_SETTING_PATH([Data file path], NUT_DATADIR, "${conftemp}", [Default path for data files]) @@ -3108,7 +3112,7 @@ dnl same for bindir conftemp="${bindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -BINDIR=${conftemp} +BINDIR="${conftemp}" NUT_REPORT_SETTING_PATH([Tool program path], BINDIR, "${conftemp}", [Default path for user executables]) @@ -3116,7 +3120,7 @@ dnl same for sbindir conftemp="${sbindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -SBINDIR=${conftemp} +SBINDIR="${conftemp}" NUT_REPORT_SETTING_PATH([System program path], SBINDIR, "${conftemp}", [Default path for system executables]) @@ -3124,7 +3128,7 @@ dnl same for libdir conftemp="${libdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -LIBDIR=${conftemp} +LIBDIR="${conftemp}" NUT_REPORT_SETTING_PATH([System library path], LIBDIR, "${conftemp}", [Default path for system libraries]) @@ -3132,7 +3136,7 @@ dnl same for libexecdir conftemp="${libexecdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" -LIBEXECDIR=${conftemp} +LIBEXECDIR="${conftemp}" NUT_REPORT_SETTING_PATH([System exec-library path], LIBEXECDIR, "${conftemp}", [Default path for system exec-libraries]) @@ -3330,6 +3334,7 @@ AC_SUBST(DRIVER_INSTALL_TARGET) AC_SUBST(NETLIBS) AC_SUBST(SERLIBS) AC_SUBST(SEMLIBS) +AC_SUBST(PREFIX) AC_SUBST(PIDPATH) AC_SUBST(STATEPATH) AC_SUBST(ALTPIDPATH) From d41436a1d85b59404347ac1527cf929dc0c6e5c2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 01:13:19 +0100 Subject: [PATCH 0225/1232] scripts/Redhat/*: drop older scripts with hardcoding, modernize .in templates for POWERDOWNFLAG and similar config options --- configure.ac | 3 ++ scripts/Makefile.am | 4 +- scripts/RedHat/.gitignore | 5 ++ scripts/RedHat/ups | 3 -- scripts/RedHat/ups.in | 3 ++ scripts/RedHat/upsd | 110 -------------------------------------- scripts/RedHat/upsd.in | 38 ++++++++----- scripts/RedHat/upsmon | 56 ------------------- scripts/RedHat/upsmon.in | 16 ++++-- 9 files changed, 47 insertions(+), 191 deletions(-) create mode 100644 scripts/RedHat/.gitignore delete mode 100644 scripts/RedHat/ups create mode 100644 scripts/RedHat/ups.in delete mode 100644 scripts/RedHat/upsd delete mode 100644 scripts/RedHat/upsmon diff --git a/configure.ac b/configure.ac index ee4ef7be41..98cd6549a5 100644 --- a/configure.ac +++ b/configure.ac @@ -3742,6 +3742,7 @@ AC_CONFIG_FILES([ lib/libnutscan.pc lib/Makefile scripts/Aix/nut-aix.spec + scripts/RedHat/ups scripts/augeas/Makefile scripts/augeas/nutnutconf.aug scripts/augeas/nutupsdconf.aug @@ -3790,6 +3791,8 @@ AC_MSG_NOTICE([Generating templated script files that should be marked executabl m4_foreach_w([SCRIPTFILE], [ scripts/Aix/nut.init scripts/HP-UX/postinstall + scripts/RedHat/upsd + scripts/RedHat/upsmon scripts/python/app/NUT-Monitor-py2gtk2 scripts/python/app/NUT-Monitor-py3qt5 scripts/augeas/gen-nutupsconf-aug.py diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 22a935e547..893d90039e 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -12,10 +12,8 @@ EXTRA_DIST = README \ perl/Nut.pm \ RedHat/halt.patch \ RedHat/README \ - RedHat/ups \ - RedHat/upsd \ + RedHat/ups.in \ RedHat/upsd.in \ - RedHat/upsmon \ RedHat/upsmon.in \ Solaris8/S99upsmon \ subdriver/gen-usbhid-subdriver.sh \ diff --git a/scripts/RedHat/.gitignore b/scripts/RedHat/.gitignore new file mode 100644 index 0000000000..63cffeda23 --- /dev/null +++ b/scripts/RedHat/.gitignore @@ -0,0 +1,5 @@ +# Generated from .in templates: +/ups +/upsd +/upsmon + diff --git a/scripts/RedHat/ups b/scripts/RedHat/ups deleted file mode 100644 index c448a09484..0000000000 --- a/scripts/RedHat/ups +++ /dev/null @@ -1,3 +0,0 @@ -# POWERDOWNFLAG *must* match that in upsmon.conf -POWERDOWNFLAG=/etc/killpower -NUTUSER=nutmon diff --git a/scripts/RedHat/ups.in b/scripts/RedHat/ups.in new file mode 100644 index 0000000000..ceed0377ec --- /dev/null +++ b/scripts/RedHat/ups.in @@ -0,0 +1,3 @@ +# POWERDOWNFLAG *must* match that in upsmon.conf +POWERDOWNFLAG="@POWERDOWNFLAG@" +NUTUSER="@RUN_AS_USER@" diff --git a/scripts/RedHat/upsd b/scripts/RedHat/upsd deleted file mode 100644 index c682cb7b65..0000000000 --- a/scripts/RedHat/upsd +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/sh -# -# chkconfig: 2345 30 90 -# -# 2003-01-31 Antonino Albanese -# Removed all old statements -# start programs as user nut -# new style starting and stopping upsd -# added reload option -# use of /etc/sysconfig/ups for POWERDOWNFLAG variable retrieving -# -# 2002-02-07 Nigel Metheringham -# made ups.conf pre-eminant, added new upsdrvctl functions, targeted for RH7.2, should -# work OK on RH 6.x, 7.x -# 2001-10-24 Peter Bieringer -# enhancements for new style drivers and controls, tested on a RHL 7.1.93 system -# -# description: NUT upsd and its drivers directly monitor a ups and \ -# make information from it available to other programs -# processname: upsd -# config: /etc/ups/upsd.conf -# config: /etc/ups/ups.conf - -PATH=/sbin:/bin:/usr/sbin:/usr/bin -export PATH - -# Source function library. -. /etc/rc.d/init.d/functions - -# POWERDOWNFLAG *must* match that in upsmon.conf -# Loading POWERDOWNFLAG from /etc/sysconfig/ups -DRIVERPATH=/sbin -if [ -f /etc/sysconfig/ups ]; then - . /etc/sysconfig/ups -else - POWERDOWNFLAG=/etc/killpower - NUTUSER=nutmon -fi -UPSDCONF=/etc/ups/upsd.conf -UPSCONF=/etc/ups/ups.conf - -# if there are no config file, bail out -[ -f $UPSDCONF ] && [ -f $UPSCONF ] || exit 0 - -runcmd() { - echo -n "$1 " - shift - if [ "$BOOTUP" = "color" ]; then - $* && echo_success || echo_failure - else - $* - fi - echo -} - -# See how we are called. -case "$1" in - start) - # new style drivers uses 'upsdrvctl' - echo -n "NUT Starting UPS model drivers: " - # starting ase nut user - daemon --user $NUTUSER `which upsdrvctl` start - echo - if [ $? -eq 0 ]; then - echo -n "NUT Starting UPS daemon: " - # starting ase nut user - daemon upsd -u $NUTUSER - echo - touch /var/lock/subsys/upsd - fi - ;; - - stop) - # new style upsd stop - action "NUT Stopping UPS daemon" \ - upsd -c stop - # new style drivers uses 'upsdrvctl' - action "NUT Stopping UPS model drivers" \ - upsdrvctl stop - - rm -f /var/lock/subsys/upsd - ;; - - powerdown) - # new style drivers - runcmd "NUT powerdown of attached UPS(es)" upsdrvctl shutdown - ;; - - restart) - $0 stop - $0 start - ;; - - reload) - # reloading upsd config files - action "NUT Reloading config files" \ - upsd -c reload - ;; - - status) - # new style drivers - action "NUT: checking UPS model drivers" upsdrvctl status - - status upsd - ;; - *) - echo "Usage: upsd {start|stop|powerdown|restart|reload|status}" - exit 1 -esac - diff --git a/scripts/RedHat/upsd.in b/scripts/RedHat/upsd.in index d2aeca92ed..f44e7fdae0 100644 --- a/scripts/RedHat/upsd.in +++ b/scripts/RedHat/upsd.in @@ -2,6 +2,9 @@ # # chkconfig: 2345 30 90 # +# 2022-01-04 Jim Klimov +# Updated .in template, double-quoted variable expansions +# # 2003-01-31 Antonino Albanese # Removed all old statements # start programs as user nut @@ -18,10 +21,10 @@ # description: NUT upsd and its drivers directly monitor a ups and \ # make information from it available to other programs # processname: upsd -# config: @sysconfdir@/upsd.conf -# config: @sysconfdir@/ups.conf +# config: @CONFPATH@/upsd.conf +# config: @CONFPATH@/ups.conf -PATH=/sbin:/bin:/usr/sbin:/usr/bin +PATH="/sbin:/bin:/usr/sbin:/usr/bin" export PATH # Source function library. @@ -29,18 +32,26 @@ export PATH # POWERDOWNFLAG *must* match that in upsmon.conf # Loading POWERDOWNFLAG from /etc/sysconfig/ups -DRIVERPATH=@DRVPATH@ +DRIVERPATH="@DRVPATH@" +NUT_SBINDIR="@SBINDIR@" if [ -f /etc/sysconfig/ups ]; then . /etc/sysconfig/ups else - POWERDOWNFLAG=/etc/killpower - NUTUSER=nutmon + POWERDOWNFLAG="@POWERDOWNFLAG@" + NUTUSER="@RUN_AS_USER@" +fi +UPSDCONF="@CONFPATH@/upsd.conf" +UPSCONF="@CONFPATH@/ups.conf" + +if [ -n "$DRIVERPATH" -a -d "$DRIVERPATH" ]; then + PATH="$DRIVERPATH:$PATH" +fi +if [ -n "$NUT_SBINDIR" -a -d "$NUT_SBINDIR" ]; then + PATH="$NUT_SBINDIR:$PATH" fi -UPSDCONF=@sysconfdir@/upsd.conf -UPSCONF=@sysconfdir@/ups.conf # if there are no config file, bail out -[ -f $UPSDCONF ] && [ -f $UPSCONF ] || exit 0 +[ -f "$UPSDCONF" ] && [ -f "$UPSCONF" ] || exit 0 runcmd() { echo -n "$1 " @@ -58,13 +69,13 @@ case "$1" in start) # new style drivers uses 'upsdrvctl' echo -n "NUT Starting UPS model drivers: " - # starting ase nut user - daemon --user $NUTUSER `which upsdrvctl` start + # starting all drivers as nut user + daemon --user "$NUTUSER" "`which upsdrvctl`" start echo if [ $? -eq 0 ]; then echo -n "NUT Starting UPS daemon: " - # starting ase nut user - daemon upsd -u $NUTUSER + # starting as nut user + daemon upsd -u "$NUTUSER" echo touch /var/lock/subsys/upsd fi @@ -107,4 +118,3 @@ case "$1" in echo "Usage: upsd {start|stop|powerdown|restart|reload|status}" exit 1 esac - diff --git a/scripts/RedHat/upsmon b/scripts/RedHat/upsmon deleted file mode 100644 index b6d77f73bc..0000000000 --- a/scripts/RedHat/upsmon +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# chkconfig: 2345 31 89 -# -# 2003-01-31 Antonino Albanese -# start program as user nut -# new style stopping upsmon -# added reload option -# -# description: upsmon talks to upsd and notifies of ups status changes \ -# also shutting systems down if required. -# processname: upsmon -# config: /etc/ups/upsmon.conf - -PATH=/sbin:/bin:/usr/sbin:/usr/bin -export PATH - -# Source function library. -. /etc/rc.d/init.d/functions - -if [ -f /etc/sysconfig/ups ]; then - . /etc/sysconfig/ups -else - POWERDOWNFLAG=/etc/killpower - NUTUSER=nutmon -fi - -# See how we are called. -case "$1" in - start) - action "NUT Starting UPS monitor" upsmon -u $NUTUSER - touch /var/lock/subsys/upsmon - ;; - stop) - action "NUT Stopping UPS monitor: " \ - upsmon -c stop - - rm -f /var/lock/subsys/upsmon - ;; - restart) - $0 stop - $0 start - ;; - reload) - action "NUT Reloading UPS monitor: " \ - upsmon -c reload - - ;; - status) - status upsmon - ;; - *) - echo "Usage: upsmon {start|stop|restart|reload|status}" - exit 1 -esac - diff --git a/scripts/RedHat/upsmon.in b/scripts/RedHat/upsmon.in index af8a7fc806..a57d1229e8 100644 --- a/scripts/RedHat/upsmon.in +++ b/scripts/RedHat/upsmon.in @@ -2,6 +2,9 @@ # # chkconfig: 2345 31 89 # +# 2022-01-04 Jim Klimov +# Updated .in template, double-quoted variable expansions +# # 2003-01-31 Antonino Albanese # start program as user nut # new style stopping upsmon @@ -10,7 +13,7 @@ # description: upsmon talks to upsd and notifies of ups status changes \ # also shutting systems down if required. # processname: upsmon -# config: @sysconfdir@/upsmon.conf +# config: @CONFPATH@/upsmon.conf PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH @@ -18,17 +21,21 @@ export PATH # Source function library. . /etc/rc.d/init.d/functions +NUT_SBINDIR="@SBINDIR@" if [ -f /etc/sysconfig/ups ]; then . /etc/sysconfig/ups else - POWERDOWNFLAG=/etc/killpower - NUTUSER=nutmon + POWERDOWNFLAG="@POWERDOWNFLAG@" + NUTUSER="@RUN_AS_USER@" +fi +if [ -n "$NUT_SBINDIR" -a -d "$NUT_SBINDIR" ]; then + PATH="$NUT_SBINDIR:$PATH" fi # See how we are called. case "$1" in start) - action "NUT Starting UPS monitor" upsmon -u $NUTUSER + action "NUT Starting UPS monitor" upsmon -u "$NUTUSER" touch /var/lock/subsys/upsmon ;; stop) @@ -53,4 +60,3 @@ case "$1" in echo "Usage: upsmon {start|stop|restart|reload|status}" exit 1 esac - From 3d711689d408c99082afcfd52aacf4bf72f4ca1f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 03:04:05 +0100 Subject: [PATCH 0226/1232] configure.ac: make default POWERDOWNFLAG configurable [#529] - escape more for autotools --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 98cd6549a5..689366c220 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,7 @@ STATEPATH="/var/state/ups" dnl NOTE: NUT legacy default, keep as is for least surprise dnl Distributions are however welcome to specify the option to use tmpfs AS_CASE([${target_os}], - [*mingw*], [POWERDOWNFLAG="C:\\killpower"], dnl NOTE: Double backslashes are correct! + [*mingw*], [POWERDOWNFLAG="C:\\\\killpower"], dnl NOTE: Double backslashes (times escaping) are correct! [POWERDOWNFLAG="/etc/killpower"] dnl POSIX systems default ) From a50700afaf155d730a484065f8d5f67dc6242c22 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 02:27:27 +0100 Subject: [PATCH 0227/1232] drivers/bcmxcp.h: fix include-fencing macros --- drivers/bcmxcp.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/bcmxcp.h b/drivers/bcmxcp.h index 7050d1c0af..054dce2466 100644 --- a/drivers/bcmxcp.h +++ b/drivers/bcmxcp.h @@ -2,8 +2,8 @@ * bcmxcp.h -- header for BCM/XCP module */ -#ifndef _POWERWARE_H -#define _POWERWARE_H +#ifndef NUT_BCMXCP_H_SEEN +#define NUT_BCMXCP_H_SEEN 1 #include "timehead.h" @@ -622,5 +622,4 @@ typedef enum ebool { FALSE, TRUE } bool_t; typedef int bool_t; #endif -#endif /*_POWERWARE_H */ - +#endif /* NUT_BCMXCP_H_SEEN */ From d74d43e165e6249f5e49e8b3b15d9f43105fdea0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 02:35:53 +0100 Subject: [PATCH 0228/1232] drivers/blazer_usb.c, drivers/nutdrv_qx.c: upsdrv_makevartable(): cosmetic fixes --- drivers/blazer_usb.c | 2 ++ drivers/nutdrv_qx.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 14ff1620d9..aa14330f7c 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -577,6 +577,8 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { addvar(VAR_VALUE, "subdriver", "Serial-over-USB subdriver selection"); + + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ nut_usb_addvars(); addvar(VAR_VALUE, "langid_fix", "Apply the language ID workaround to the krauler subdriver (0x409 or 0x4095)"); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 414318730e..bd378b647d 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -2670,6 +2670,7 @@ void upsdrv_makevartable(void) #ifdef QX_USB addvar(VAR_VALUE, "subdriver", "Serial-over-USB subdriver selection"); + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ nut_usb_addvars(); From 3b1b921669da9ca7f360cbcfa9645fa6816f66ed Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 02:36:29 +0100 Subject: [PATCH 0229/1232] drivers/nutdrv_atcl_usb.c: upsdrv_makevartable(): refer to nut_usb_addvars() [#1754] --- drivers/Makefile.am | 2 +- drivers/nutdrv_atcl_usb.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index c5ec006cad..7a20400a56 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -212,7 +212,7 @@ bcmxcp_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm blazer_usb_SOURCES = blazer.c blazer_usb.c $(LIBUSB_IMPL) usb-common.c blazer_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm -nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c usb-common.c +nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c $(LIBUSB_IMPL) usb-common.c nutdrv_atcl_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) richcomm_usb_SOURCES = richcomm_usb.c usb-common.c diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index 144bd8cdc8..e6c4bb0a2b 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -24,11 +24,12 @@ */ #include "main.h" +#include "nut_libusb.h" #include "usb-common.h" /* driver version */ #define DRIVER_NAME "'ATCL FOR UPS' USB driver" -#define DRIVER_VERSION "1.16" +#define DRIVER_VERSION "1.17" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -679,5 +680,6 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { - addvar(VAR_VALUE, "vendor", "USB vendor string (or NULL if none)"); + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ + nut_usb_addvars(); } From 613b8d6017093d84c6949b658884bedb777810fc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 02:36:41 +0100 Subject: [PATCH 0230/1232] drivers/richcomm_usb.c: upsdrv_makevartable(): refer to nut_usb_addvars() [#1754] --- drivers/Makefile.am | 2 +- drivers/richcomm_usb.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 7a20400a56..d55b3d67a8 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -215,7 +215,7 @@ blazer_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c $(LIBUSB_IMPL) usb-common.c nutdrv_atcl_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -richcomm_usb_SOURCES = richcomm_usb.c usb-common.c +richcomm_usb_SOURCES = richcomm_usb.c $(LIBUSB_IMPL) usb-common.c richcomm_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) riello_usb_SOURCES = riello.c riello_usb.c $(LIBUSB_IMPL) usb-common.c diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 5ac775c4cf..a2359d697d 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -24,12 +24,13 @@ */ #include "main.h" +#include "nut_libusb.h" #include "usb-common.h" #include "nut_stdint.h" /* driver version */ #define DRIVER_NAME "Richcomm dry-contact to USB driver" -#define DRIVER_VERSION "0.10" +#define DRIVER_VERSION "0.11" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -734,4 +735,6 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ + nut_usb_addvars(); } From e6bc8aae0465fce63b72ada6a4f657ce0c866268 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 02:36:57 +0100 Subject: [PATCH 0231/1232] drivers/riello_usb.c: upsdrv_makevartable(): refer to nut_usb_addvars() [#1754] --- drivers/riello_usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 0dc257ddf9..8430850f9a 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -34,7 +34,7 @@ #include "riello.h" #define DRIVER_NAME "Riello USB driver" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" #define DEFAULT_OFFDELAY 5 /*!< seconds (max 0xFF) */ #define DEFAULT_BOOTDELAY 5 /*!< seconds (max 0xFF) */ @@ -831,7 +831,8 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { - + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ + nut_usb_addvars(); } void upsdrv_initups(void) From 5b95c5e3cc219c6b15b9a079ac3a54f3c3748458 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 09:56:03 +0100 Subject: [PATCH 0232/1232] NEWS: mention the fix for USB matching options fix for some drivers --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index a7268c1547..239c37613b 100644 --- a/NEWS +++ b/NEWS @@ -137,6 +137,9 @@ https://github.com/networkupstools/nut/milestone/8 - NUT software-only drivers (dummy-ups, clone, clone-outlet) separated from serial drivers in respective Makefile and configure script options [#1446] + - Fixed support for common USB matching options ("vendor", "device", "bus", + etc.) for `riello_usb`, `richcomm_usb` and `nutdrv_atcl_usb` [#1763] + - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] From b0e8d4a3aaeb9bdf38a798886236e4f715d754e5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:04:51 +0100 Subject: [PATCH 0233/1232] Introduce docs/man/nut_usb_addvars.txt (initial content from blazer-common.txt with updated formatting) --- docs/man/Makefile.am | 2 ++ docs/man/blazer-common.txt | 33 +-------------------------- docs/man/nut_usb_addvars.txt | 43 ++++++++++++++++++++++++++++++++++++ docs/nut.dict | 3 ++- 4 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 docs/man/nut_usb_addvars.txt diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index b0b8080a02..146e7c525c 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -528,11 +528,13 @@ SRC_USB_LIBUSB_PAGES = \ blazer-common.txt \ blazer_usb.txt \ nutdrv_atcl_usb.txt \ + nut_usb_addvars.txt \ richcomm_usb.txt \ riello_usb.txt \ tripplite_usb.txt \ usbhid-ups.txt +# NOTE: nut_usb_addvars and blazer-common are not standalone man pages if WITH_MANS MAN_USB_LIBUSB_PAGES = \ bcmxcp_usb.8 \ diff --git a/docs/man/blazer-common.txt b/docs/man/blazer-common.txt index dc53dc8feb..9520bcdc75 100644 --- a/docs/man/blazer-common.txt +++ b/docs/man/blazer-common.txt @@ -136,38 +136,7 @@ ifdef::blazer_usb[] USB INTERFACE ONLY ~~~~~~~~~~~~~~~~~~ -*vendorid =* 'regex':: -*productid =* 'regex':: -*vendor =* 'regex':: -*product =* 'regex':: -*serial =* 'regex':: - -Select a specific UPS, in case there is more than one connected via -USB. Each option specifies an extended regular expression (see -*regex(7)*) that must match the UPS's entire vendor/product/serial -string (minus any surrounding whitespace), or the whole 4-digit -hexadecimal code for vendorid and productid. Try *-DD* for -finding out the strings to match. -+ -Examples: - - - `-x vendor="Foo.Corporation.*"` - - `-x vendorid=051d*` (APC) - - `-x product=".*(Smart|Back)-?UPS.*"` - -*bus =* 'regex':: - -Select a UPS on a specific USB bus or group of buses. The argument is -a regular expression that must match the bus name where the UPS is -connected (e.g. bus="002", bus="00[2-3]"). - -*device =* 'regex':: - -Select a UPS on a specific USB device or group of devices. The argument is -a regular expression that must match the device name where the UPS is -connected (e.g. device="001", device="00[1-2]"). -Note that device numbers are not guaranteed by the OS to be stable across -re-boots or device re-plugging. +include::nut_usb_addvars.txt[] *subdriver =* 'string':: diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt new file mode 100644 index 0000000000..c5cd61ac1b --- /dev/null +++ b/docs/man/nut_usb_addvars.txt @@ -0,0 +1,43 @@ +//////// +This file is included into other man pages, where appropriate, +by their choice of markup and sectioning (usually lands into +"USB INTERFACE ONLY" for serial/usb or "EXTRA ARGUMENTS"). + +Keep in sync with nut_usb_addvars() method provided by +* drivers/libusb0.c +* drivers/libusb1.c +* drivers/usb-common.h +//////// + +*vendorid =* 'regex':: +*productid =* 'regex':: +*vendor =* 'regex':: +*product =* 'regex':: +*serial =* 'regex':: + +Select a specific UPS, in case there is more than one connected via +USB. Each option specifies an extended regular expression (see +*regex(7)* that must match the UPS's entire vendor/product/serial +string (minus any surrounding whitespace), or the whole 4-digit +hexadecimal code for `vendorid` and `productid`. Try *-DD* for +finding out the strings to match. ++ +Examples: + +- `-x vendor="Foo.Corporation.*"` +- `-x vendorid="051d*"` (APC) +- `-x product=".*(Smart|Back)-?UPS.*"` + +*bus =* 'regex':: + +Select a UPS on a specific USB bus or group of buses. The argument is +a regular expression that must match the bus name where the UPS is +connected (e.g. `bus="002"` or `bus="00[2-3]"`). + +*device =* 'regex':: + +Select a UPS on a specific USB device or group of devices. The argument is +a regular expression that must match the device name where the UPS is +connected (e.g. `device="001"` or `device="00[1-2]"`). +Note that device numbers are not guaranteed by the OS to be stable across +re-boots or device re-plugging. diff --git a/docs/nut.dict b/docs/nut.dict index 5e5b651a6a..b091553076 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3062 utf-8 +personal_ws-1.1 en 3063 utf-8 AAS ABI ACFAIL @@ -1408,6 +1408,7 @@ addenum addinfo addr addrange +addvars adelsystem adkorte adm From a52957dff5cf5f4337b60f80611e68e334ef8d81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:11:48 +0100 Subject: [PATCH 0234/1232] docs/man/bcmxcp_usb.txt: mention lack of support for common nut_usb_addvars [#1764] --- docs/man/bcmxcp_usb.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/man/bcmxcp_usb.txt b/docs/man/bcmxcp_usb.txt index 2eae9f5e91..32f8261c86 100644 --- a/docs/man/bcmxcp_usb.txt +++ b/docs/man/bcmxcp_usb.txt @@ -27,10 +27,25 @@ EXTRA ARGUMENTS This driver supports the following optional settings in the linkman:ups.conf[5]. -*shutdown_delay=*'delay':: +*shutdown_delay =* 'delay':: The number of seconds that the UPS should wait between receiving the shutdown command and actually shutting off. +NOTE: This driver does not currently support USB-matching settings common +to other drivers, such as *vendor*, *vendorid*, *product*, *productid*, +*serial*, *device* or *bus*. + +//////// +The note above may be addressed by +https://github.com/networkupstools/nut/issues/1764 +When that happens, replace it by the following lines: + +USB INTERFACE ONLY +~~~~~~~~~~~~~~~~~~ + +include::nut_usb_addvars.txt[] +//////// + DEFAULT VALUES FOR THE EXTRA ARGUMENTS -------------------------------------- From a2ce60b05788f60271811d24ec21080a5fa0b039 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:19:12 +0100 Subject: [PATCH 0235/1232] Revert "drivers/nutdrv_atcl_usb.c: upsdrv_makevartable(): refer to nut_usb_addvars() [#1754]" This reverts commit 3b1b921669da9ca7f360cbcfa9645fa6816f66ed. This driver uses a very custom device-matcher. --- NEWS | 2 +- drivers/Makefile.am | 2 +- drivers/nutdrv_atcl_usb.c | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 239c37613b..f41161ad9a 100644 --- a/NEWS +++ b/NEWS @@ -138,7 +138,7 @@ https://github.com/networkupstools/nut/milestone/8 serial drivers in respective Makefile and configure script options [#1446] - Fixed support for common USB matching options ("vendor", "device", "bus", - etc.) for `riello_usb`, `richcomm_usb` and `nutdrv_atcl_usb` [#1763] + etc.) for `riello_usb` and `richcomm_usb` [#1763] - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] diff --git a/drivers/Makefile.am b/drivers/Makefile.am index d55b3d67a8..31fcd7120b 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -212,7 +212,7 @@ bcmxcp_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm blazer_usb_SOURCES = blazer.c blazer_usb.c $(LIBUSB_IMPL) usb-common.c blazer_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm -nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c $(LIBUSB_IMPL) usb-common.c +nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c usb-common.c nutdrv_atcl_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) richcomm_usb_SOURCES = richcomm_usb.c $(LIBUSB_IMPL) usb-common.c diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index e6c4bb0a2b..e6473d2231 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -24,12 +24,11 @@ */ #include "main.h" -#include "nut_libusb.h" #include "usb-common.h" /* driver version */ #define DRIVER_NAME "'ATCL FOR UPS' USB driver" -#define DRIVER_VERSION "1.17" +#define DRIVER_VERSION "1.16" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -680,6 +679,8 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { - /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ - nut_usb_addvars(); + /* NOTE: This driver uses a very custom device matching method, + * so does not involve nut_usb_addvars() method like others do. + */ + addvar(VAR_VALUE, "vendor", "USB vendor string (or NULL if none)"); } From 219e9399829bd55ad2572f12dac77506edfc5fd7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:37:05 +0100 Subject: [PATCH 0236/1232] docs/man/nutdrv_atcl_usb.txt: this driver uses a very custom device-matcher with only a vendor string --- docs/man/nutdrv_atcl_usb.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/man/nutdrv_atcl_usb.txt b/docs/man/nutdrv_atcl_usb.txt index e955a01068..77bdeb6b00 100644 --- a/docs/man/nutdrv_atcl_usb.txt +++ b/docs/man/nutdrv_atcl_usb.txt @@ -34,11 +34,18 @@ EXTRA ARGUMENTS This driver supports the following optional setting: -*vendor*='name':: +*vendor =* 'name':: + In case your iManufacturer (Vendor) string does not exactly match -+ATCL FOR UPS+, you may provide an alternate string here. Note that a more -likely case is that your device is handled by another driver for +0001:0000+ -devices, such as linkman:nutdrv_qx[8]. ++ATCL FOR UPS+, you may provide an alternate string here (or specify "NULL" if +the device does not provide a vendor string but you want this driver to match). ++ +Note that a more likely case for mismatch is that your device is handled by +another driver for +0001:0000+ devices, such as linkman:nutdrv_qx[8]. ++ +NOTE: This driver does not intend to support USB-matching settings common to +other drivers, such as *vendorid*, *product*, *productid*, *serial*, *device* +or *bus*; also the *vendor* setting supported here is not a regular expression. BUGS ---- From ab131ef66c64268386d004d844be80dd7023077f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:39:55 +0100 Subject: [PATCH 0237/1232] drivers/nutdrv_atcl_usb.c: report device_match_func() failure and refer to nutdrv_qx more prominently --- drivers/nutdrv_atcl_usb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index e6473d2231..b515c25ef2 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -82,7 +82,8 @@ static int device_match_func(USBDevice_t *device, void *privdata) return 1; } } - upsdebugx(1, "To keep trying (in case your device does not have a vendor string), use vendor=NULL"); + upsdebugx(0, "To keep trying (in case your device does not have a vendor string), use vendor=NULL. " + "Have you tried the nutdrv_qx driver?"); return 0; } @@ -97,15 +98,16 @@ static int device_match_func(USBDevice_t *device, void *privdata) upsdebugx(3, "Matched device with vendor='%s'.", requested_vendor); return 1; } else { - upsdebugx(2, "idVendor=%04x and idProduct=%04x, " - "but provided vendor '%s' does not match device: '%s'.", + upsdebugx(0, "idVendor=%04x and idProduct=%04x, " + "but provided vendor '%s' does not match device: '%s'. " + "Have you tried the nutdrv_qx driver?", device->VendorID, device->ProductID, requested_vendor, device->Vendor); return 0; } } /* TODO: automatic way of suggesting other drivers? */ - upsdebugx(2, "idVendor=%04x and idProduct=%04x, " + upsdebugx(0, "idVendor=%04x and idProduct=%04x, " "but device vendor string '%s' does not match expected string '%s'. " "Have you tried the nutdrv_qx driver?", device->VendorID, device->ProductID, device->Vendor, USB_VENDOR_STRING); From 6be2215f1ff5f99d31efe05a7c5d210d89c2f2ad Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:51:12 +0100 Subject: [PATCH 0238/1232] docs/man/nut_usb_addvars.txt: pick up "port" mention from nutdrv_qx.txt and expand on it --- docs/man/nut_usb_addvars.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index c5cd61ac1b..1bff517ab0 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -9,6 +9,16 @@ Keep in sync with nut_usb_addvars() method provided by * drivers/usb-common.h //////// +*port =* 'string':: + +Some 'value' must be set, typically *auto*. ++ +NOTE: This could be a device filesystem path like `/dev/usb/hiddev0` but current +use of libusb API precludes knowing and matching by such identifiers. They may +also be inherently unreliable (dependent on re-plugging and enumeration order). +At this time the actual 'value' is ignored, but some 'port' must be there +syntactically. + *vendorid =* 'regex':: *productid =* 'regex':: *vendor =* 'regex':: From 2d21fad9085f33294f0d5127a4997dfd378b7f33 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:54:55 +0100 Subject: [PATCH 0239/1232] docs/man/nutdrv_qx.txt: refactor to include nut_usb_addvars.txt --- docs/man/nutdrv_qx.txt | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index d46e3c510b..558f105300 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -319,32 +319,7 @@ If you find that your UPS isn't detected or the communication with the UPS is un USB INTERFACE ONLY ~~~~~~~~~~~~~~~~~~ -*port =* 'string':: -You must set 'value' to *auto*. - -*vendorid =* 'regex':: -*productid =* 'regex':: -*vendor =* 'regex':: -*product =* 'regex':: -*serial =* 'regex':: -Select a specific UPS, in case there is more than one connected via USB. -Each option specifies an extended regular expression (see *regex(7)*) that must match the UPS's entire vendor/product/serial string (minus any surrounding whitespace), or the whole 4-digit hexadecimal code for vendorid and productid. -Try *-DD* for finding out the strings to match. -+ -Examples: - - - `-x vendor="Foo.Corporation.*"` - - `-x vendorid=051d*` (APC) - - `-x product=".*(Smart|Back)-?UPS.*"` - -*bus =* 'regex':: -Select a UPS on a specific USB bus or group of buses. -The argument is a regular expression that must match the bus name where the UPS is connected (e.g. +bus="002"+, +bus="00[2-3]"+). - -*device =* 'regex':: -Select a UPS on a specific USB device or group of devices. -The argument is a regular expression that must match the device name where the UPS is connected (e.g. +device="001"+, +device="00[1-2]"+). -Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. +include::nut_usb_addvars.txt[] *subdriver =* 'string':: Select a serial-over-USB subdriver to use. From 8706be5c17b3d9df3f3d0ebab95481129449b871 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 11:57:57 +0100 Subject: [PATCH 0240/1232] docs/man/richcomm_usb.txt, docs/man/riello_usb.txt: refactor to include nut_usb_addvars.txt [#1763] --- docs/man/richcomm_usb.txt | 5 +++++ docs/man/riello_usb.txt | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/docs/man/richcomm_usb.txt b/docs/man/richcomm_usb.txt index fe53b14920..e9416dfc0c 100644 --- a/docs/man/richcomm_usb.txt +++ b/docs/man/richcomm_usb.txt @@ -22,6 +22,11 @@ As such, all the limitations of the underlying contact closure interface apply. This means that you will only get the essentials in ups.status: OL, OB, and LB. See also linkman:genericups[8]. +EXTRA ARGUMENTS +--------------- + +include::nut_usb_addvars.txt[] + BUGS ---- diff --git a/docs/man/riello_usb.txt b/docs/man/riello_usb.txt index 1c4ffd6e43..4301894e3a 100644 --- a/docs/man/riello_usb.txt +++ b/docs/man/riello_usb.txt @@ -24,6 +24,10 @@ riello_usb supports all recent Riello UPS with USB. Older Riello UPS products are not supported. +EXTRA ARGUMENTS +--------------- + +include::nut_usb_addvars.txt[] AUTHOR ------ From 443a4316e0cd93436ce7ae271c65fd778a73337c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:04:16 +0100 Subject: [PATCH 0241/1232] docs/man/nut_usb_addvars.txt: update with references to lsusb and regex from tripplite_usb.txt --- docs/man/nut_usb_addvars.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 1bff517ab0..e78d4eafe1 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -27,10 +27,13 @@ syntactically. Select a specific UPS, in case there is more than one connected via USB. Each option specifies an extended regular expression (see -*regex(7)* that must match the UPS's entire vendor/product/serial -string (minus any surrounding whitespace), or the whole 4-digit -hexadecimal code for `vendorid` and `productid`. Try *-DD* for -finding out the strings to match. +*regex(7)* for more information on regular expressions), which +must match the UPS's entire respective vendor/product/serial string +(minus any surrounding whitespace), or the whole 4-digit +hexadecimal code for `vendorid` and `productid`. ++ +Try *lsusb(8)* or running this NUT driver with *-DD* command-line +argument for finding out the strings to match. + Examples: @@ -42,12 +45,14 @@ Examples: Select a UPS on a specific USB bus or group of buses. The argument is a regular expression that must match the bus name where the UPS is -connected (e.g. `bus="002"` or `bus="00[2-3]"`). +connected (e.g. `bus="002"` or `bus="00[2-3]"`) as seen in +`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. *device =* 'regex':: Select a UPS on a specific USB device or group of devices. The argument is a regular expression that must match the device name where the UPS is -connected (e.g. `device="001"` or `device="00[1-2]"`). +connected (e.g. `device="001"` or `device="00[1-2]"`) as seen in +`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. From 9096b3637faaf9bcdb7ff43c5a9f87dcff878b25 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:13:50 +0100 Subject: [PATCH 0242/1232] docs/man/tripplite_usb.txt: refactor to include nut_usb_addvars.txt --- docs/man/tripplite_usb.txt | 62 +++++++++++++++----------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/docs/man/tripplite_usb.txt b/docs/man/tripplite_usb.txt index cad5a80f22..06aa7f8b70 100644 --- a/docs/man/tripplite_usb.txt +++ b/docs/man/tripplite_usb.txt @@ -61,6 +61,31 @@ EXTRA ARGUMENTS This driver supports the following optional settings in the linkman:ups.conf[5] file (or with '-x' on the command line): +include::nut_usb_addvars.txt[] + +[NOTE] +.Notes for `tripplite_usb` driver handling of common USB matching settings: +====== +* *product* is a regular expression to match the product string for the UPS. +This would be useful if you have two different Tripp Lite UPS models connected +to the same monitoring system, and you want to be sure that you shut them down +in the correct order. ++ +This regex is matched against the full USB product string as seen in +lsusb(8). The `ups.model` in the linkman:upsc[1] output only lists the name +after `TRIPP LITE`, so to match a SMART2200RMXL2U, you could use the regex +`.*SMART2200.*`. + +* The *productid* is a regular expression which matches the UPS PID as four +hexadecimal digits. So far, the only known devices that work with this driver +have PID `0001`. + +* The *serial* option may be or not be helpful: it does not appear that these +particular Tripp Lite UPSes supported by this driver use the `iSerial` +descriptor field to return a serial number. However, in case your unit does, +you may specify it here. +====== + *offdelay*:: This setting controls the delay between receiving the "kill" command ('-k') @@ -75,43 +100,6 @@ range of 10% through 100%, so the resting voltage of the charged battery can be used for *battery_max*, and the higher float charge voltage should not cause problems. -*bus*:: - -This regular expression is used to match the USB bus (as seen in -`/proc/bus/usb/devices` or lsusb(8); including leading zeroes). - -*device*:: - -This regular expression is used to match the USB device (as seen in -`/proc/bus/usb/devices` or lsusb(8); including leading zeroes). -Note that device numbers are not guaranteed by the OS to be stable across -re-boots or device re-plugging. - -*product*:: - -A regular expression to match the product string for the UPS. This would be -useful if you have two different Tripp Lite UPS models connected to the -system, and you want to be sure that you shut them down in the correct order. - -NOTE: This regex is matched against the full USB product string as seen in -lsusb(8). The `ups.model` in the linkman:upsc[1] output only lists the name after -`TRIPP LITE`, so to match a SMART2200RMXL2U, you could use the regex -`.*SMART2200.*`. - -*productid*:: - -The productid is a regular expression which matches the UPS PID as four -hexadecimal digits. So far, the only devices that work with this driver have -PID `0001`. - -*serial*:: - -It does not appear that these particular Tripp Lite UPSes use the `iSerial` -descriptor field to return a serial number. However, in case your unit does, -you may specify it here. - -For more information on regular expressions, see regex(7) - RUNTIME VARIABLES ----------------- From 1b660761aec6123b013db8c8bde31501da8f00d9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:19:15 +0100 Subject: [PATCH 0243/1232] docs/man/nut_usb_addvars.txt: update with reasoning for nut_usb_addvars settings from usbhid-ups.txt --- docs/man/nut_usb_addvars.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index e78d4eafe1..07cc120259 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -19,6 +19,11 @@ also be inherently unreliable (dependent on re-plugging and enumeration order). At this time the actual 'value' is ignored, but some 'port' must be there syntactically. +It is possible to control multiple UPS units simultaneously by running several +instances of this driver, provided they can be uniquely distinguished by setting +some combination of the *vendor*, *product*, *vendorid*, *productid*, *serial*, +*bus* and/or *device* options detailed below. + *vendorid =* 'regex':: *productid =* 'regex':: *vendor =* 'regex':: From 85bb4c9404fd6b829b42864adeab7f9c925be8f6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:21:41 +0100 Subject: [PATCH 0244/1232] docs/man/usbhid-ups.txt: refactor to include nut_usb_addvars.txt --- docs/man/usbhid-ups.txt | 45 +++++++---------------------------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index ab4e8a2470..5a93a16925 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -52,6 +52,8 @@ EXTRA ARGUMENTS This driver also supports the following optional settings: +include::nut_usb_addvars.txt[] + *offdelay*='num':: Set the timer before the UPS is turned off after the kill power command is sent (via the *-k* switch). @@ -110,39 +112,6 @@ It is also always possible that NUT fix-ups cause issues on some devices, whether due to NUT bugs or because the vendor protocol implementation is broken in more than one place. -*vendor*='regex':: -*product*='regex':: -*serial*='regex':: -*vendorid*='regex':: -*productid*='regex':: - -Select a specific UPS, in case there is more than one connected via -USB. Each option specifies an extended regular expression (see -regex(7)) that must match the UPS's entire vendor/product/serial -string (minus any surrounding whitespace), or the whole 4-digit -hexadecimal code for vendorid and productid. Try *-DD* for -finding out the strings to match. -+ -Examples: - - - `-x vendor="Foo.Corporation.*"` - - `-x vendorid=051d*` (APC) - - `-x product=".*(Smart|Back)-?UPS.*"` - -*bus*='regex':: - -Select a UPS on a specific USB bus or group of buses. The argument is -a regular expression that must match the bus name where the UPS is -connected (e.g. bus="002", bus="00[2-3]"). - -*device =* 'regex':: - -Select a UPS on a specific USB device or group of devices. The argument is -a regular expression that must match the device name where the UPS is -connected (e.g. device="001", device="00[1-2]"). -Note that device numbers are not guaranteed by the OS to be stable across -re-boots or device re-plugging. - *explore*:: With this option, the driver will connect to any device, including ones that are not yet supported. This must always be combined with the @@ -194,11 +163,11 @@ IMPLEMENTATION Selecting a specific UPS ~~~~~~~~~~~~~~~~~~~~~~~~ -The driver ignores the "port" value in *ups.conf*. Unlike previous -versions of this driver, it is now possible to control multiple UPS -units simultaneously with this driver, provided they can be distinguished -by setting some combination of the "vendor", "product", "serial", -"vendorid", and "productid" options. For instance: +As mentioned above, the driver ignores the "port" value in *ups.conf*. +Unlike previous versions of this driver, it is now possible to control +multiple UPS units simultaneously with this driver, provided they can +be distinguished by setting some combination of the device-matching options. +For instance: [mge] driver = usbhid-ups From 5e4e903840a8bbb95b2edc038a72b9c5b593d461 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:24:31 +0100 Subject: [PATCH 0245/1232] NEWS: man pages refactored for USB matching options description [#1766] --- NEWS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f41161ad9a..f55b544b6b 100644 --- a/NEWS +++ b/NEWS @@ -138,7 +138,9 @@ https://github.com/networkupstools/nut/milestone/8 serial drivers in respective Makefile and configure script options [#1446] - Fixed support for common USB matching options ("vendor", "device", "bus", - etc.) for `riello_usb` and `richcomm_usb` [#1763] + etc.) for `riello_usb` and `richcomm_usb` [#1763] and updated man pages + of all USB drivers using these options to include the same description + [#1766] - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] From 8de193828a3db834f52f5a6ba0e4eca4d60ceb94 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 15:06:50 +0100 Subject: [PATCH 0246/1232] docs/man/nut_usb_addvars.txt: document usb_set_altinterface setting (from libusb{0,1}.c) --- docs/man/nut_usb_addvars.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 07cc120259..3f6b3f5ccf 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -61,3 +61,9 @@ connected (e.g. `device="001"` or `device="00[1-2]"`) as seen in `/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. + +*usb_set_altinterface =* 'bAlternateSetting':: + +Force redundant call to `usb_set_altinterface()`, especially if needed +for devices serving multiple USB roles where the UPS is not represented +by the interface number `0` (default). From 9d5ebafe7d01a1bd16f499f3da414665522a9ea1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 15:55:53 +0100 Subject: [PATCH 0247/1232] docs/man/richcomm_usb.txt: hide from docs the USB matching settings that are not currently handled by the driver [#1768] --- docs/man/richcomm_usb.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/man/richcomm_usb.txt b/docs/man/richcomm_usb.txt index e9416dfc0c..4ee57e6006 100644 --- a/docs/man/richcomm_usb.txt +++ b/docs/man/richcomm_usb.txt @@ -22,10 +22,14 @@ As such, all the limitations of the underlying contact closure interface apply. This means that you will only get the essentials in ups.status: OL, OB, and LB. See also linkman:genericups[8]. +//////// +TODO: Uncomment after solving https://github.com/networkupstools/nut/issues/1768 + EXTRA ARGUMENTS --------------- include::nut_usb_addvars.txt[] +//////// BUGS ---- From 9f4ac1e2ec54183feaa47975c43b67d7fd98e38e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 17:06:16 +0100 Subject: [PATCH 0248/1232] drivers/richcomm_usb.c: hide from help() the USB matching settings that are not currently handled by the driver [#1768] --- drivers/richcomm_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index a2359d697d..c1d128340b 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -736,5 +736,7 @@ void upsdrv_help(void) void upsdrv_makevartable(void) { /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ + /* TODO: Uncomment while addressing https://github.com/networkupstools/nut/issues/1768 nut_usb_addvars(); + */ } From 39b6e48ec329ad17185e4db6822aef655520f814 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:51:35 +0100 Subject: [PATCH 0249/1232] docs/nut-names.txt: update WITH_UNMAPPED_DATA_POINTS [#1699, #1742] --- docs/nut-names.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index f5b3758801..a497df356f 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -43,7 +43,9 @@ strings in those reports. The `unmapped` entries should not be exposed in "production" builds of the NUT drivers. They are an aid for developers to know that such entries are served by their device, so an existing standard NUT name can be assigned for the concept (or new name negotiated with the -community), but are normally hidden with `#if 0` clauses. +community), but are normally hidden with `#if WITH_UNMAPPED_DATA_POINTS` +clauses which can be enabled in custom NUT builds by use of +`./configure --with-unmapped-data-points` option. NOTE: In the descriptions, "opaque" means programs should not attempt to parse the value for that variable as it may vary greatly from one UPS From 4a718168a36a3253d4ca831bbe6ec206b86a10c2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 12:53:07 +0100 Subject: [PATCH 0250/1232] docs/nut-names.txt: update with final RFC 9271 reference --- docs/nut-names.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index a497df356f..6f12ad2156 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -4,9 +4,10 @@ NUT variable names and instant commands endif::external_title[] [NOTE] -.RFC xxxx Recording Document +.RFC 9271 Recording Document ==== -This document is defined by (pending) RFC xxxx and is referenced as the +This document is defined by RFC 9271 published by IETF at +https://www.rfc-editor.org/info/rfc9271 and is referenced as the document of record for the variable names and the instant commands used in the protocol described by the RFC. From 10be1a9658522b5c50b3b02983c92f755fdcd0e8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 13:47:29 +0100 Subject: [PATCH 0251/1232] drivers/main.c, docs/nut-names.txt: introduce "driver.state" tracking [#1767] --- docs/nut-names.txt | 10 ++++++++++ docs/nut.dict | 3 ++- drivers/main.c | 20 +++++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index f5b3758801..f486ce08f0 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -700,6 +700,16 @@ driver: Internal driver information cmdline -x) setting | (varies) | driver.flag.xxx | Flag xxx (ups.conf or cmdline -x) status | enabled (or absent) +| driver.state | Current state in driver's + lifecycle, primarily to help + readers discern long-running + init (with full device walk) + or cleanup stages from + the stable working loop | init.starting, init.quiet, + init.device, init.info, + init.updateinfo (first walk), + updateinfo, quiet, dumping, + cleanup.upsdrv, cleanup.exit |=============================================================================== server: Internal server information diff --git a/docs/nut.dict b/docs/nut.dict index 71a21ac48f..7bf317615d 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3067 utf-8 +personal_ws-1.1 en 3068 utf-8 AAS ABI ACFAIL @@ -2146,6 +2146,7 @@ licensor licensors liebert liebertgxt +lifecycle linesensitivity linevoltage linkdoc diff --git a/drivers/main.c b/drivers/main.c index 8f7dce69cd..0bb8616ace 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -631,8 +631,16 @@ static void vartab_free(void) } } +static void exit_upsdrv_cleanup(void) +{ + dstate_setinfo("driver.state", "cleanup.upsdrv"); + upsdrv_cleanup(); +} + static void exit_cleanup(void) { + dstate_setinfo("driver.state", "cleanup.exit"); + free(chroot_path); free(device_path); free(user); @@ -691,6 +699,8 @@ int main(int argc, char **argv) int i, do_forceshutdown = 0; int update_count = 0; + dstate_setinfo("driver.state", "init.starting"); + atexit(exit_cleanup); /* pick up a default from configure --with-user */ @@ -996,10 +1006,12 @@ int main(int argc, char **argv) * when its a pdu! */ dstate_setinfo("device.type", "ups"); + dstate_setinfo("driver.state", "init.device"); upsdrv_initups(); + dstate_setinfo("driver.state", "init.quiet"); /* UPS is detected now, cleanup upon exit */ - atexit(upsdrv_cleanup); + atexit(exit_upsdrv_cleanup); /* now see if things are very wrong out there */ if (upsdrv_info.status == DRV_BROKEN) { @@ -1023,8 +1035,11 @@ int main(int argc, char **argv) syslogbit_set(); /* get the base data established before allowing connections */ + dstate_setinfo("driver.state", "init.info"); upsdrv_initinfo(); + dstate_setinfo("driver.state", "init.updateinfo"); upsdrv_updateinfo(); + dstate_setinfo("driver.state", "init.quiet"); if (dstate_getinfo("driver.flag.ignorelb")) { int have_lb_method = 0; @@ -1154,12 +1169,15 @@ int main(int argc, char **argv) gettimeofday(&timeout, NULL); timeout.tv_sec += poll_interval; + dstate_setinfo("driver.state", "updateinfo"); upsdrv_updateinfo(); + dstate_setinfo("driver.state", "quiet"); /* Dump the data tree (in upsc-like format) to stdout and exit */ if (dump_data) { /* Wait for 'dump_data' update loops to ensure data completion */ if (update_count == dump_data) { + dstate_setinfo("driver.state", "dumping"); dstate_dump(); exit_flag = 1; } From 4afb5e183ffbe8a5e45ea0d7a4dec517cf35a0f9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 14:09:25 +0100 Subject: [PATCH 0252/1232] drivers/main.c: report where driver.state changes from init.* to just before regular work [#1767] --- drivers/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index 0bb8616ace..5ffcaa9977 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1162,8 +1162,14 @@ int main(int argc, char **argv) writepid(pidfn); /* PID changes when backgrounding */ } - while (!exit_flag) { + dstate_setinfo("driver.state", "quiet"); + if (dump_data) { + upsdebugx(1, "Driver initialization completed, beginning data dump (%d loops)", dump_data); + } else { + upsdebugx(1, "Driver initialization completed, beginning regular infinite loop"); + } + while (!exit_flag) { struct timeval timeout; gettimeofday(&timeout, NULL); From 3ad247469ba56114851d394ad167593a86d6036b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 14:45:37 +0100 Subject: [PATCH 0253/1232] driver/*.c: report reconnection attempts as a "driver.state" [#1767] --- docs/nut-names.txt | 2 ++ drivers/adelsystem_cbi.c | 3 +++ drivers/bcmxcp_usb.c | 5 +++++ drivers/blazer_usb.c | 5 +++++ drivers/generic_modbus.c | 3 +++ drivers/main.c | 2 ++ drivers/nutdrv_qx.c | 5 +++++ drivers/powerman-pdu.c | 3 +++ drivers/richcomm_usb.c | 3 +++ drivers/riello_usb.c | 5 +++++ drivers/tripplite_usb.c | 6 ++++++ drivers/usbhid-ups.c | 7 +++++++ 12 files changed, 49 insertions(+) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index f486ce08f0..b51e65e925 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -708,6 +708,8 @@ driver: Internal driver information the stable working loop | init.starting, init.quiet, init.device, init.info, init.updateinfo (first walk), + reconnect.trying, + reconnect.updateinfo, updateinfo, quiet, dumping, cleanup.upsdrv, cleanup.exit |=============================================================================== diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index fb7b93abff..e86a16a5c9 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -1281,6 +1281,7 @@ void modbus_reconnect(void) int rval; upsdebugx(1, "modbus_reconnect, trying to reconnect to modbus server"); + dstate_setinfo("driver.state", "reconnect.trying"); /* clear current modbus context */ modbus_close(mbctx); @@ -1340,5 +1341,7 @@ void modbus_reconnect(void) } /* #elif (defined NUT_MODBUS_TIMEOUT_ARG_timeval) // some un-castable type in fields */ #endif /* NUT_MODBUS_TIMEOUT_ARG_* */ + + dstate_setinfo("driver.state", "quiet"); } diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index 50ac843e7a..b5aeabb52f 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -385,13 +385,18 @@ void upsdrv_cleanup(void) void upsdrv_reconnect(void) { + dstate_setinfo("driver.state", "reconnect.trying"); + upsdebugx(4, "=================================================="); upsdebugx(4, "= device has been disconnected, try to reconnect ="); upsdebugx(4, "=================================================="); nutusb_close(upsdev, "USB"); upsdev = NULL; + upsdrv_initups(); + + dstate_setinfo("driver.state", "quiet"); } /* USB functions */ diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index aa14330f7c..74d0710b84 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -445,11 +445,15 @@ ssize_t blazer_command(const char *cmd, char *buf, size_t buflen) ssize_t ret; if (udev == NULL) { + dstate_setinfo("driver.state", "reconnect.trying"); + ret = usb->open_dev(&udev, &usbdevice, reopen_matcher, NULL); if (ret < 1) { return ret; } + + dstate_setinfo("driver.state", "reconnect.updateinfo"); } ret = (*subdriver_command)(cmd, buf, buflen); @@ -496,6 +500,7 @@ ssize_t blazer_command(const char *cmd, char *buf, size_t buflen) case LIBUSB_ERROR_NOT_FOUND: /* No such file or directory */ fallthrough_case_reconnect: /* Uh oh, got to reconnect! */ + dstate_setinfo("driver.state", "reconnect.trying"); usb->close_dev(udev); udev = NULL; break; diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 20eda551e9..ab53f0673f 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -1038,6 +1038,7 @@ void modbus_reconnect(void) int rval; upsdebugx(2, "modbus_reconnect, trying to reconnect to modbus server"); + dstate_setinfo("driver.state", "reconnect.trying"); /* clear current modbus context */ modbus_close(mbctx); @@ -1097,4 +1098,6 @@ void modbus_reconnect(void) } /* #elif (defined NUT_MODBUS_TIMEOUT_ARG_timeval) // some un-castable type in fields */ #endif /* NUT_MODBUS_TIMEOUT_ARG_* */ + + dstate_setinfo("driver.state", "quiet"); } diff --git a/drivers/main.c b/drivers/main.c index 5ffcaa9977..828787e5db 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1037,6 +1037,8 @@ int main(int argc, char **argv) /* get the base data established before allowing connections */ dstate_setinfo("driver.state", "init.info"); upsdrv_initinfo(); + /* Note: a few drivers also call their upsdrv_updateinfo() during + * their upsdrv_initinfo(), possibly to impact the initialization */ dstate_setinfo("driver.state", "init.updateinfo"); upsdrv_updateinfo(); dstate_setinfo("driver.state", "init.quiet"); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index bd378b647d..61400b4cce 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3163,11 +3163,15 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) # endif /* QX_SERIAL (&& QX_USB)*/ if (udev == NULL) { + dstate_setinfo("driver.state", "reconnect.trying"); + ret = usb->open_dev(&udev, &usbdevice, reopen_matcher, NULL); if (ret < 1) { return ret; } + + dstate_setinfo("driver.state", "reconnect.updateinfo"); } ret = (*subdriver_command)(cmd, buf, buflen); @@ -3229,6 +3233,7 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) case LIBUSB_ERROR_NOT_FOUND: /* No such file or directory */ fallthrough_case_reconnect: /* Uh oh, got to reconnect! */ + dstate_setinfo("driver.state", "reconnect.trying"); usb->close_dev(udev); udev = NULL; break; diff --git a/drivers/powerman-pdu.c b/drivers/powerman-pdu.c index df4e91f3e5..d1e55bfcdd 100644 --- a/drivers/powerman-pdu.c +++ b/drivers/powerman-pdu.c @@ -191,6 +191,8 @@ static int reconnect_ups(void) { pm_err_t rv; + dstate_setinfo("driver.state", "reconnect.trying"); + upsdebugx(4, "==================================================="); upsdebugx(4, "= connection lost with Powerman, try to reconnect ="); upsdebugx(4, "==================================================="); @@ -202,6 +204,7 @@ static int reconnect_ups(void) if ((rv = pm_connect(device_path, NULL, &pm, 0)) != PM_ESUCCESS) return 0; else { + dstate_setinfo("driver.state", "quiet"); upsdebugx(4, "connection restored with Powerman"); return 1; } diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index c1d128340b..3df85f2449 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -638,11 +638,13 @@ void upsdrv_updateinfo(void) int ret, online, battery_normal; if (!udev) { + dstate_setinfo("driver.state", "reconnect.trying"); ret = usb_device_open(&udev, &usbdevice, &device_matcher, &driver_callback); if (ret < 0) { return; } + dstate_setinfo("driver.state", "reconnect.updateinfo"); } ret = query_ups(reply); @@ -651,6 +653,7 @@ void upsdrv_updateinfo(void) usb_comm_fail("Query to UPS failed"); dstate_datastale(); + dstate_setinfo("driver.state", "reconnect.trying"); usb_device_close(udev); udev = NULL; diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 8430850f9a..36c451e208 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -348,13 +348,17 @@ static int riello_command(uint8_t *cmd, uint8_t *buf, uint16_t length, uint16_t int ret; if (udev == NULL) { + dstate_setinfo("driver.state", "reconnect.trying"); + ret = usb->open_dev(&udev, &usbdevice, reopen_matcher, &driver_callback); upsdebugx (3, "riello_command err udev NULL : %d ", ret); if (ret < 0) return ret; + dstate_setinfo("driver.state", "reconnect.updateinfo"); upsdrv_initinfo(); /* reconnect usb cable */ + dstate_setinfo("driver.state", "quiet"); } ret = (*subdriver_command)(cmd, buf, length, buflen); @@ -404,6 +408,7 @@ static int riello_command(uint8_t *cmd, uint8_t *buf, uint16_t length, uint16_t case LIBUSB_ERROR_NOT_FOUND: /* No such file or directory */ fallthrough_case_reconnect: /* Uh oh, got to reconnect! */ + dstate_setinfo("driver.state", "reconnect.trying"); usb->close_dev(udev); udev = NULL; break; diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 62a8bcab9a..96abce57d1 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -325,6 +325,8 @@ static int reconnect_ups(void) return 1; } + dstate_setinfo("driver.state", "reconnect.trying"); + upsdebugx(2, "=================================================="); upsdebugx(2, "= device has been disconnected, try to reconnect ="); upsdebugx(2, "=================================================="); @@ -337,6 +339,7 @@ static int reconnect_ups(void) } hd = &curDevice; + dstate_setinfo("driver.state", "quiet"); return ret; } @@ -552,6 +555,7 @@ static void usb_comm_fail(int res, const char *msg) #endif default: + dstate_setinfo("driver.state", "reconnect.trying"); upslogx(LOG_WARNING, "%s: Device detached? (error %d: %s)", msg, res, nut_usb_strerror(res)); @@ -563,7 +567,9 @@ static void usb_comm_fail(int res, const char *msg) if(hd) { upslogx(LOG_NOTICE, "Successfully reconnected"); try = 0; + dstate_setinfo("driver.state", "reconnect.updateinfo"); upsdrv_initinfo(); + dstate_setinfo("driver.state", "quiet"); } else { if(try > MAX_RECONNECT_TRIES) { fatalx(EXIT_FAILURE, "Too many unsuccessful reconnection attempts"); diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index d250b548b5..f6ba14c968 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -888,10 +888,12 @@ void upsdrv_updateinfo(void) case LIBUSB_ERROR_NO_MEM: /* Insufficient memory */ fallthrough_reconnect: /* Uh oh, got to reconnect! */ + dstate_setinfo("driver.state", "reconnect.trying"); hd = NULL; return; case LIBUSB_ERROR_IO: /* I/O error */ /* Uh oh, got to reconnect, with a special suggestion! */ + dstate_setinfo("driver.state", "reconnect.trying"); interrupt_pipe_EIO_count++; hd = NULL; return; @@ -1510,11 +1512,13 @@ static bool_t hid_ups_walk(walkmode_t mode) case LIBUSB_ERROR_NO_MEM: /* Insufficient memory */ fallthrough_reconnect: /* Uh oh, got to reconnect! */ + dstate_setinfo("driver.state", "reconnect.trying"); hd = NULL; return FALSE; case LIBUSB_ERROR_IO: /* I/O error */ /* Uh oh, got to reconnect, with a special suggestion! */ + dstate_setinfo("driver.state", "reconnect.trying"); interrupt_pipe_EIO_count++; hd = NULL; return FALSE; @@ -1595,6 +1599,8 @@ static int reconnect_ups(void) char *val; int wait_before_reconnect = 0; + dstate_setinfo("driver.state", "reconnect.trying"); + /* Init time to wait before trying to reconnect (seconds) */ val = getval(HU_VAR_WAITBEFORERECONNECT); if (val) { @@ -1627,6 +1633,7 @@ static int reconnect_ups(void) return 1; } + dstate_setinfo("driver.state", "quiet"); return 0; } From 0a0c941620033dbfd920b771559e1a77ead38bf6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Jan 2023 14:55:40 +0100 Subject: [PATCH 0254/1232] NEWS: announce new "driver.state" feature [#1767] --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 9afce2500f..5a392451cc 100644 --- a/NEWS +++ b/NEWS @@ -145,6 +145,9 @@ https://github.com/networkupstools/nut/milestone/8 - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] + - Each driver should now report its `driver.state` to help readers determine + whether it is initializing, reconnecting, or running regular loops [#1767] + - Code which resolves full paths to libraries should now consider the common environment variable `LD_LIBRARY_PATH` as a preferred possible override to built-in paths (note that most operating systems advise against setting From c5d025570228ba0c853384f0075a20859e97952d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 00:26:43 +0100 Subject: [PATCH 0255/1232] drivers/libusb{0,1}.c, drivers/usb-common.c: update comments in device matcher code --- drivers/libusb0.c | 5 ++++- drivers/libusb1.c | 15 ++++++++++----- drivers/usb-common.c | 3 +++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index eef5dd2d51..acd475299d 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -363,6 +363,9 @@ static int libusb_open(usb_dev_handle **udevp, goto next_device; } } + + /* If we got here, none of the matchers said + * that the device is not what we want. */ upsdebugx(2, "Device matches"); /* Now we have matched the device we wanted. Claim it. */ @@ -375,8 +378,8 @@ static int libusb_open(usb_dev_handle **udevp, #ifdef WIN32 usb_set_configuration(udev, 1); #endif - while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { + while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { upsdebugx(2, "failed to claim USB device: %s", usb_strerror()); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 6627ebc83d..5ba241a3fc 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -331,8 +331,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, goto next_device; } } - upsdebugx(2, "Device matches"); + /* If we got here, none of the matchers said + * that the device is not what we want. */ + upsdebugx(2, "Device matches"); upsdebugx(2, "Reading first configuration descriptor"); ret = libusb_get_config_descriptor(device, @@ -379,20 +381,23 @@ static int nut_libusb_open(libusb_device_handle **udevp, /* TODO: Align with libusb1 - initially from Windows branch made against libusb0 */ libusb_set_configuration(udev, 1); #endif + while ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { upsdebugx(2, "failed to claim USB device: %s", libusb_strerror((enum libusb_error)ret)); # ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER - if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { + if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # else /* if defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) */ - if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { + if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # endif - if (ret == LIBUSB_ERROR_NOT_FOUND) + if (ret == LIBUSB_ERROR_NOT_FOUND) { + /* logged as "Entity not found" if this persists */ upsdebugx(2, "Kernel driver already detached"); - else + } else { upsdebugx(1, "failed to detach kernel driver from USB device: %s", libusb_strerror((enum libusb_error)ret)); + } } else { upsdebugx(2, "detached kernel driver from USB device..."); } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 5f2dc168d1..a45a621168 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -311,6 +311,9 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) upsdebugx(3, "%s: matching a device...", __func__); + /* NOTE: Here and below the "detailed" logging is commented away + * because data->regex[] elements are not strings anymore! */ + r = match_regex_hex(data->regex[0], hd->VendorID); if (r != 1) { /* From 58bcd75be4d209f8615c8cf3f4fd1d76af303c7e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 00:27:33 +0100 Subject: [PATCH 0256/1232] drivers/usb-common.h: update amount of supported possibly unique fields to try for device matching --- drivers/usb-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 0cc760f0f7..a3513adf0d 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -463,7 +463,7 @@ /*! * USBDevice_t: Describe a USB device. This structure contains exactly - * the 5 pieces of information by which a USB device identifies + * the 7 pieces of information by which a USB device identifies * itself, so it serves as a kind of "fingerprint" of the device. This * information must be matched exactly when reopening a device, and * therefore must not be "improved" or updated by a client From edf1e3006ea59380d3bc0575f7e29169de6cdc3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 00:26:43 +0100 Subject: [PATCH 0257/1232] drivers/libusb{0,1}.c, drivers/usb-common.c: update comments in device matcher code --- drivers/libusb0.c | 5 ++++- drivers/libusb1.c | 15 ++++++++++----- drivers/usb-common.c | 3 +++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index eef5dd2d51..acd475299d 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -363,6 +363,9 @@ static int libusb_open(usb_dev_handle **udevp, goto next_device; } } + + /* If we got here, none of the matchers said + * that the device is not what we want. */ upsdebugx(2, "Device matches"); /* Now we have matched the device we wanted. Claim it. */ @@ -375,8 +378,8 @@ static int libusb_open(usb_dev_handle **udevp, #ifdef WIN32 usb_set_configuration(udev, 1); #endif - while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { + while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { upsdebugx(2, "failed to claim USB device: %s", usb_strerror()); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 6627ebc83d..5ba241a3fc 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -331,8 +331,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, goto next_device; } } - upsdebugx(2, "Device matches"); + /* If we got here, none of the matchers said + * that the device is not what we want. */ + upsdebugx(2, "Device matches"); upsdebugx(2, "Reading first configuration descriptor"); ret = libusb_get_config_descriptor(device, @@ -379,20 +381,23 @@ static int nut_libusb_open(libusb_device_handle **udevp, /* TODO: Align with libusb1 - initially from Windows branch made against libusb0 */ libusb_set_configuration(udev, 1); #endif + while ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { upsdebugx(2, "failed to claim USB device: %s", libusb_strerror((enum libusb_error)ret)); # ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER - if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { + if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # else /* if defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) */ - if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { + if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # endif - if (ret == LIBUSB_ERROR_NOT_FOUND) + if (ret == LIBUSB_ERROR_NOT_FOUND) { + /* logged as "Entity not found" if this persists */ upsdebugx(2, "Kernel driver already detached"); - else + } else { upsdebugx(1, "failed to detach kernel driver from USB device: %s", libusb_strerror((enum libusb_error)ret)); + } } else { upsdebugx(2, "detached kernel driver from USB device..."); } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 5f2dc168d1..a45a621168 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -311,6 +311,9 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) upsdebugx(3, "%s: matching a device...", __func__); + /* NOTE: Here and below the "detailed" logging is commented away + * because data->regex[] elements are not strings anymore! */ + r = match_regex_hex(data->regex[0], hd->VendorID); if (r != 1) { /* From 320d401e48dcf0950016d8dcab5f2b34bfa9424c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 02:32:18 +0100 Subject: [PATCH 0258/1232] Introduce an `allow_duplicates` flag for common USB matching options [#1756] --- NEWS | 4 ++++ docs/man/nut_usb_addvars.txt | 23 +++++++++++++++++++++++ drivers/libusb0.c | 25 +++++++++++++++++++++++-- drivers/libusb1.c | 21 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 9afce2500f..45596a56b3 100644 --- a/NEWS +++ b/NEWS @@ -142,6 +142,10 @@ https://github.com/networkupstools/nut/milestone/8 of all USB drivers using these options to include the same description [#1766] + - Added an `allow_duplicates` flag for common USB matching options which + may help monitor several related no-name devices (although without knowing + reliably which one is which... better than nothing) [#1756] + - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 3f6b3f5ccf..0ad8547fa2 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -62,6 +62,29 @@ connected (e.g. `device="001"` or `device="00[1-2]"`) as seen in Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. +*allow_duplicates*:: + +If you have several UPS devices which may not be uniquely identified by +the options above (e.g. only VID:PID can be discovered there), this flag +allows each driver instance where it is set to take the first match if +available, or proceed to try another. ++ +Normally the driver initialization would abort at this point claiming +"Resource busy" or similar error, assuming that the otherwise properly +matched device is unique -- and some other process already handles it. ++ +[WARNING] +========= +This feature is inherently non-deterministic! +The association of driver instance name to actual device +may vary between runs! + +If you only care to know that *at least* one of your no-name UPSes +is online, this option can help. + +If you must really know *which* one, it will not! +========= + *usb_set_altinterface =* 'bAlternateSetting':: Force redundant call to `usb_set_altinterface()`, especially if needed diff --git a/drivers/libusb0.c b/drivers/libusb0.c index acd475299d..8d8c9e1bf0 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -76,6 +76,17 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); + + /* Warning: this feature is inherently non-deterministic! + * If you only care to know that at least one of your no-name UPSes is online, + * this option can help. If you must really know which one, it will not! + */ + addvar(VAR_FLAG, "allow_duplicates", + "If you have several UPS devices which may not be uniquely " + "identified by options above, allow each driver instance with this " + "option to take the first match if available, or try another " + "(association of driver to device may vary between runs)"); + addvar(VAR_VALUE, "usb_set_altinterface", "Force redundant call to usb_set_altinterface() (value=bAlternateSetting; default=0)"); dstate_setinfo("driver.version.usb", "libusb-0.1 (or compat)"); @@ -379,10 +390,15 @@ static int libusb_open(usb_dev_handle **udevp, usb_set_configuration(udev, 1); #endif - while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { + while ((ret = usb_claim_interface(udev, usb_subdriver.hid_rep_index)) < 0) { upsdebugx(2, "failed to claim USB device: %s", usb_strerror()); + if (ret == LIBUSB_ERROR_BUSY && testvar("allow_duplicates")) { + upsdebugx(2, "Configured to allow_duplicates so looking for another similar device"); + goto next_device; + } + if (usb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index) < 0) { upsdebugx(2, "failed to detach kernel driver from USB device: %s", usb_strerror()); @@ -402,7 +418,12 @@ static int libusb_open(usb_dev_handle **udevp, usb_strerror()); } #else - if (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { + if ((ret = usb_claim_interface(udev, usb_subdriver.hid_rep_index)) < 0) { + if (ret == LIBUSB_ERROR_BUSY && testvar("allow_duplicates")) { + upsdebugx(2, "Configured to allow_duplicates so looking for another similar device"); + goto next_device; + } + fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]@%d/%d: %s", curDevice->VendorID, curDevice->ProductID, diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 5ba241a3fc..80154a99b4 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -66,6 +66,17 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); + + /* Warning: this feature is inherently non-deterministic! + * If you only care to know that at least one of your no-name UPSes is online, + * this option can help. If you must really know which one, it will not! + */ + addvar(VAR_FLAG, "allow_duplicates", + "If you have several UPS devices which may not be uniquely " + "identified by options above, allow each driver instance with this " + "option to take the first match if available, or try another " + "(association of driver to device may vary between runs)"); + addvar(VAR_VALUE, "usb_set_altinterface", "Force redundant call to usb_set_altinterface() (value=bAlternateSetting; default=0)"); #ifdef LIBUSB_API_VERSION @@ -386,6 +397,11 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "failed to claim USB device: %s", libusb_strerror((enum libusb_error)ret)); + if (ret == LIBUSB_ERROR_BUSY && testvar("allow_duplicates")) { + upsdebugx(2, "Configured to allow_duplicates so looking for another similar device"); + goto next_device; + } + # ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # else /* if defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) */ @@ -417,6 +433,11 @@ static int nut_libusb_open(libusb_device_handle **udevp, } #else if ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS ) { + if (ret == LIBUSB_ERROR_BUSY && testvar("allow_duplicates")) { + upsdebugx(2, "Configured to allow_duplicates so looking for another similar device"); + goto next_device; + } + libusb_free_config_descriptor(conf_desc); libusb_free_device_list(devlist, 1); fatalx(EXIT_FAILURE, From f28ca242241edc5c95dee6940aea638fecb8a4db Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 13:56:35 +0100 Subject: [PATCH 0259/1232] NEWS: mention update of NUT COPYING file [#1758] --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 9afce2500f..8bb53f3e64 100644 --- a/NEWS +++ b/NEWS @@ -224,6 +224,9 @@ https://github.com/networkupstools/nut/milestone/8 include NUT headers. Sort of regression by NUT 2.8.0 (note those consumers still have to re-declare some numeric variable types used) [#1638, #1615] + - The `COPYING` file was updated with licenses and attribution for certain + source code files and blocks coming from the Internet originally [#1758] + --------------------------------------------------------------------------- Release notes for NUT 2.8.0 - what's new since 2.7.4: From ef9857965d2807bdf169c20fea8735ce80318608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 5 Jan 2023 16:21:20 +0100 Subject: [PATCH 0260/1232] Add experimental prefix missed in 7ef2874e81 drivers/nutdrv_qx_masterguard.c: Add "experimental." prefix in masterguard_claim(). Needed because that prefix had been added (in 7ef2874e81952fac532014a8840a217cf1d636b6) to the variable names in the masterguard_qx2nut[] table. --- drivers/nutdrv_qx_masterguard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nutdrv_qx_masterguard.c b/drivers/nutdrv_qx_masterguard.c index 71984c6de6..e44b1ed382 100644 --- a/drivers/nutdrv_qx_masterguard.c +++ b/drivers/nutdrv_qx_masterguard.c @@ -936,11 +936,11 @@ static int masterguard_claim(void) { item_t *item; /* mandatory values */ char *mandatory[] = { - "series", /* SKIP */ + "experimental.series", /* SKIP */ "device.model", /* minimal number of battery packs */ "ups.power.nominal", /* load computation */ "ups.id", /* slave address */ - "output_voltages", /* output voltages enum */ + "experimental.output_voltages", /* output voltages enum */ #if 0 "battery.packs", /* battery voltage computation */ #endif From d5aea8520e4ebc97c9b1208ef0f4064c01ba4045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 5 Jan 2023 16:27:01 +0100 Subject: [PATCH 0261/1232] Set curDevice->Device during USB enumeration During USB enumeration, set curDevice->Device. Try to use libusb1's port number obtained by libusb_get_port_number(), but that seems useless at least on NetBSD. So, use devnum (the enumeration loop variable), which at least makes two identically looking USB UPSen distinguishable again. Maybe we want to add a Port property set to what libusb_get_port_number() reports? Previously missed during refactoring to libusb1. --- drivers/libusb1.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 5ba241a3fc..b908c8de1e 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -151,7 +151,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, struct libusb_config_descriptor *conf_desc = NULL; const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; - uint8_t bus; + uint8_t bus, port; int ret, res; unsigned char buf[20]; const unsigned char *p; @@ -235,6 +235,17 @@ static int nut_libusb_open(libusb_device_handle **udevp, fatal_with_errno(EXIT_FAILURE, "Out of memory"); } sprintf(curDevice->Bus, "%03d", bus); + port = libusb_get_port_number(device); + curDevice->Device = (char *)malloc(4); + if (curDevice->Device == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } +#if 0 + sprintf(curDevice->Device, "%03d", port); +#else + sprintf(curDevice->Device, "%03d", devnum); +#endif curDevice->VendorID = dev_desc.idVendor; curDevice->ProductID = dev_desc.idProduct; curDevice->bcdDevice = dev_desc.bcdDevice; From a4bc1865206d4446f4e330ab3815d8d2065f65ca Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Thu, 5 Jan 2023 11:06:17 -0500 Subject: [PATCH 0262/1232] MAINTAINERS: add pkgsrc --- MAINTAINERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b2fcaf8ae6..87b03d11c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -60,6 +60,10 @@ P: Arnaud Quette M: aquette@debian.org S: Maintained: Official Debian packages +P: Greg Troxel +M: gdt@lexort.com +S: Maintained: pkgsrc (sysutils/ups-nut) + Everything else =============== From cbfe3a8ccd72cd890a72bc2d81c293d849e5cb23 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 13:10:55 +0100 Subject: [PATCH 0263/1232] drivers/libusb1.c: handle non-zero libusb port numbers as valid [#1774] --- drivers/libusb1.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index b908c8de1e..9b571659ff 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -234,18 +234,36 @@ static int nut_libusb_open(libusb_device_handle **udevp, libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - sprintf(curDevice->Bus, "%03d", bus); + if (bus > 0) { + sprintf(curDevice->Bus, "%03d", bus); + } else { + upsdebugx(1, "%s: invalid libusb bus number %i", + __func__, bus); + } + port = libusb_get_port_number(device); curDevice->Device = (char *)malloc(4); if (curDevice->Device == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } -#if 0 - sprintf(curDevice->Device, "%03d", port); -#else - sprintf(curDevice->Device, "%03d", devnum); -#endif + if (port > 0) { + /* 0 means not available, e.g. lack of platform support */ + sprintf(curDevice->Device, "%03d", port); + } else { + if (devnum <= 999) { + /* Log visibly so users know their number discovered + * from `lsusb` or `dmesg` (if any) was ignored */ + upsdebugx(0, "%s: invalid libusb port number %i, " + "falling back to enumeration order counter %" PRIuSIZE, + __func__, port, devnum); + sprintf(curDevice->Device, "%03d", (int)devnum); + } else { + upsdebugx(1, "%s: invalid libusb port number %i", + __func__, port); + } + } + curDevice->VendorID = dev_desc.idVendor; curDevice->ProductID = dev_desc.idProduct; curDevice->bcdDevice = dev_desc.bcdDevice; From da131f52d29c969d1acd7da36294cd54dc3fc6fc Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Fri, 6 Jan 2023 13:35:27 +0000 Subject: [PATCH 0264/1232] huawei-ups2000.c: log error code/string for Modbus failures Currently, failures in modbus_read_registers() or modbus_write_registers() do not show any error code or message in the log, making it difficult to debug. This commit logs the error code, errno, and modbus_strerror() if an error occurs. Furthermore, the log level of a fatal warning has been changed from LOG_WARNING to LOG_ERR (LOG_WARNING was previously used due to an oversight). Signed-off-by: Yifeng Li --- drivers/huawei-ups2000.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index 3de07cf320..81d5924d40 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -1949,6 +1949,8 @@ static int ups2000_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *des /* generic retry for modbus read failures. */ if (retry_status == RETRY_ENABLE && r != nb) { + upslogx(LOG_WARNING, "modbus_read_registers() failed (%d, errno %d): %s", + r, errno, modbus_strerror(errno)); upslogx(LOG_WARNING, "Register %04d has a read failure. Retrying...", addr); sleep(1); continue; @@ -1974,7 +1976,9 @@ static int ups2000_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *des } /* Give up */ - upslogx(LOG_WARNING, "Register %04d has a fatal read failure.", addr); + upslogx(LOG_ERR, "modbus_read_registers() failed (%d, errno %d): %s", + r, errno, modbus_strerror(errno)); + upslogx(LOG_ERR, "Register %04d has a fatal read failure.", addr); retry_status = RETRY_DISABLE_TEMPORARY; return r; } @@ -1994,6 +1998,8 @@ static int ups2000_write_registers(modbus_t *ctx, int addr, int nb, uint16_t *sr /* generic retry for modbus write failures. */ if (retry_status == RETRY_ENABLE && r != nb) { + upslogx(LOG_WARNING, "modbus_write_registers() failed (%d, errno %d): %s", + r, errno, modbus_strerror(errno)); upslogx(LOG_WARNING, "Register %04d has a write failure. Retrying...", addr); sleep(1); continue; @@ -2005,7 +2011,9 @@ static int ups2000_write_registers(modbus_t *ctx, int addr, int nb, uint16_t *sr } /* Give up */ - upslogx(LOG_WARNING, "Register %04d has a fatal write failure.", addr); + upslogx(LOG_ERR, "modbus_write_registers() failed (%d, errno %d): %s", + r, errno, modbus_strerror(errno)); + upslogx(LOG_ERR, "Register %04d has a fatal write failure.", addr); retry_status = RETRY_DISABLE_TEMPORARY; return r; } From b2e24539532b4190e9cdf7895e70078fb0948013 Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Thu, 5 Jan 2023 19:19:28 -0500 Subject: [PATCH 0265/1232] docs/man: Clarify Best driver support for Fortress LI660 --- docs/man/bestfcom.txt | 3 ++- docs/man/bestfortress.txt | 1 + docs/man/bestups.txt | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/man/bestfcom.txt b/docs/man/bestfcom.txt index 67001851ca..cc40c2be31 100644 --- a/docs/man/bestfcom.txt +++ b/docs/man/bestfcom.txt @@ -17,7 +17,8 @@ SUPPORTED HARDWARE ------------------ Best Power Fortress/Ferrups implementing the Fortress UPS Protocol -(f-command set). +(f-command set). (For older Fortress units, see +linkman:bestfortress[8].) EXTRA ARGUMENTS --------------- diff --git a/docs/man/bestfortress.txt b/docs/man/bestfortress.txt index aac0b8b448..71d346c4ee 100644 --- a/docs/man/bestfortress.txt +++ b/docs/man/bestfortress.txt @@ -17,6 +17,7 @@ SUPPORTED HARDWARE ------------------ This driver supports old Best Fortress UPS equipment using a serial connection. +One example is the "Fortress LI660", sold in (at least) 1995. EXTRA ARGUMENTS --------------- diff --git a/docs/man/bestups.txt b/docs/man/bestups.txt index f2904bf2d1..d4287e573c 100644 --- a/docs/man/bestups.txt +++ b/docs/man/bestups.txt @@ -22,9 +22,9 @@ but if you are running it to try setting up a new device, please consider the newer linkman:nutdrv_qx[8] instead, which should handle all 'Q*' protocol variants for NUT. -Please do also report if your device works with this driver, -but linkman:nutdrv_qx[8] would not actually support it with any -subdriver! +If your device works with this driver, but does not work with +linkman:nutdrv_qx[8], please report this via the mailing list or issue +tracker. SUPPORTED HARDWARE ------------------ @@ -37,7 +37,8 @@ Best 610 is supported using the `ID' option. Other UPS hardware using the Phoenixtec protocol should also work, but they will generate a warning since their battery information is not known. -This driver does not support some older Best/SOLA units. +This driver does not support some older Best/SOLA units. (For older +Fortress units, see linkman:bestfortress[8].) EXTRA ARGUMENTS --------------- From ed8e05e5ce827c577288fefebfb9657d4237d55b Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Thu, 5 Jan 2023 19:20:00 -0500 Subject: [PATCH 0266/1232] docs/man: Clarify upsdrvctl shutdown --- docs/man/upsdrvctl.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 8bf336e504..24bc90366b 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -74,11 +74,15 @@ Start the UPS driver(s). In case of failure, further attempts may be executed by using the 'maxretry' and 'retrydelay' options - see linkman:ups.conf[5]. *stop*:: -Stop the UPS driver(s). +Stop the UPS driver(s). This does not send commands to the UPS. *shutdown*:: -Command the UPS driver(s) to run their shutdown sequence. Drivers are -stopped according to their sdorder value - see linkman:ups.conf[5]. +Command the UPS driver(s) to run their shutdown sequence. This +assumes that the driver is no longer running, and starts a fresh +instance via "driver -k". It is intended to be used as the last step +in system shutdown, after the filesystems are no longer mounted rw. +Drivers are stopped according to their sdorder value - see +linkman:ups.conf[5]. WARNING: this will probably power off your computers, so don't play around with this option. Only use it when your systems are prepared From 1aef935f5e1d1d9ff5ff690de9ceb8c6d8a7534e Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Fri, 6 Jan 2023 09:32:29 -0500 Subject: [PATCH 0267/1232] docs/man/upsmon.txt: Explain POWERDOWNFLAG Document that it is removed at successful startup --- docs/man/upsmon.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index 313cf2983c..97d9cc9895 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -406,6 +406,15 @@ can not guarantee that if a new power outage happens, their UPS would safely shut down your systems again. So it is deemed better and safer to stay dark until batteries become sufficiently charged. +When it is time to shut down, upsmon creates POWERDOWNFLAG to +communicate to the operating system that the UPS should be commanded +off late in the shutdown sequence. This file is removed if present +when upsmon starts, so that the next normal shutdown does not cause +the UPS to be turned off. (The file can't in general be removed +during shutdown because the filesystem might be read only. If the +file is in a RAM-backed filesystem, the it won't be present and the +check to remove it won't fire.) + SIMULATING POWER FAILURES ------------------------- From 0a82f9a79285e9fe9ec8d75471b8b2f1834e61b6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 13:51:05 +0100 Subject: [PATCH 0268/1232] m4/nut_check_libsystemd.m4, configure.ac: On systemd aware OSes, optionally integrate with sd_notify() [#1590] --- configure.ac | 36 ++++++++++++--- docs/config-prereqs.txt | 14 +++++- m4/nut_check_libsystemd.m4 | 90 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 m4/nut_check_libsystemd.m4 diff --git a/configure.ac b/configure.ac index 689366c220..1534256f3d 100644 --- a/configure.ac +++ b/configure.ac @@ -2596,6 +2596,7 @@ fi AC_MSG_RESULT([${solarisinit}]) AM_CONDITIONAL(WITH_SOLARIS_INIT, test x"$solarisinit" = x"yes") + dnl Note: Currently there is no reliable automatic detection - dnl users have to ask they want systemd units installed, or dnl risk auto-detection like seen below. @@ -2629,15 +2630,16 @@ else have_systemd="no" AC_MSG_RESULT(no) fi -dnl Note: we may want tighter integration, e.g. systemd-notify support at -dnl a later point. That would be a further option/flag. This one is a very -dnl basic yes/no toggle. -NUT_REPORT_FEATURE([consider systemd support], [${have_systemd}], [], - [HAVE_SYSTEMD], [Define to consider systemd support]) +dnl Note: we may want tighter integration, e.g. systemd-notify support +dnl configured as a further option/flag (see --with-systemd below). +dnl This one is a very basic yes/no toggle for unit file delivery. +NUT_REPORT_FEATURE([consider basic systemd support], [${have_systemd}], [], + [HAVE_SYSTEMD], [Define to consider basic systemd support (provide units and configuration files)]) dnl This option is only provided so that make distcheck can override it, dnl otherwise we ask pkg-config whenever --with-systemdsystemunitdir is dnl given + AC_MSG_CHECKING(whether to install systemd shutdown files) AC_ARG_WITH([systemdshutdowndir], AS_HELP_STRING([--with-systemdshutdowndir=DIR], [Directory for systemd shutdown scripts (auto)]), @@ -2670,6 +2672,7 @@ else AC_MSG_RESULT(no) fi + dnl Note: if (systemd-)tmpfiles tech is present, it can be useful even for dnl daemons starting not as systemd units, to pre-create /var/run/nut etc. AC_MSG_CHECKING([whether to install systemd tmpfiles files]) @@ -2701,6 +2704,27 @@ else AC_MSG_RESULT(no) fi + +dnl Note: we may want binaries with sd_notify and similar features regardless +dnl of building and delivering unit files (which may be crafted separately). +AC_MSG_CHECKING(whether to build binaries with tighter systemd integration support) +NUT_ARG_WITH([libsystemd], [build binaries with tighter systemd integration (notifications etc)], [auto]) +NUT_CHECK_LIBSYSTEMD + +AS_IF([test x"${nut_with_libsystemd}" = xyes && test x"${nut_have_libsystemd}" != xyes], + [AC_MSG_ERROR([--with-libsystemd was requested, but the library was not found or usable])]) +AS_CASE(["${nut_with_libsystemd}"], + [yes|no], [have_libsystemd="${nut_with_libsystemd}"], + [AS_IF([test x"${nut_have_libsystemd}" = xyes], + [with_libsystemd="yes"], + [with_libsystemd="no"]) + ]) +AC_MSG_RESULT(${with_libsystemd}) + +NUT_REPORT_FEATURE([build with tighter systemd support], [${with_libsystemd}], [], + [WITH_LIBSYSTEMD], [Define to build with tighter systemd support (sd_notify etc)]) + + dnl dnl Tests for CppUnit availability and usability (will be built if we can, dnl and if valgrind is enabled for this configuration - reported below). @@ -3327,6 +3351,8 @@ AC_SUBST(LIBWRAP_CFLAGS) AC_SUBST(LIBWRAP_LIBS) AC_SUBST(LIBLTDL_CFLAGS) AC_SUBST(LIBLTDL_LIBS) +AC_SUBST(LIBSYSTEMD_CFLAGS) +AC_SUBST(LIBSYSTEMD_LIBS) AC_SUBST(DRIVER_BUILD_LIST) AC_SUBST(DRIVER_MAN_LIST) AC_SUBST(DRIVER_MAN_LIST_PAGES) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 8a4fc62027..3b40f4736f 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -151,6 +151,10 @@ metadata about recently published package revisions: :; apt-get install \ libgd-dev +# Optionally for sd_notify integration: +:; apt-get install \ + libsystemd-dev + # NOTE: Some older Debian-like distributions, could ship "libcrypto-dev" # and/or "openssl-dev" instead of "libssl-dev" by its modern name :; apt-get install \ @@ -254,7 +258,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. ------ :; yum install \ ccache time \ - file systemd-devel \ + file \ git python perl curl \ make autoconf automake libtool-ltdl-devel libtool \ valgrind \ @@ -282,6 +286,10 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. :; yum install \ gd-devel +# Optionally for sd_notify integration: +:; yum install \ + systemd-devel + # NOTE: "libusbx" is the CentOS way of naming "libusb-1.0" # vs. the older "libusb" as the package with "libusb-0.1" :; yum install \ @@ -358,6 +366,10 @@ Install tools and prerequisites for NUT: :; pacman -S --needed \ gd +# Optionally for sd_notify integration: +:; pacman -S --needed \ + systemd + :; pacman -S --needed \ cppunit \ openssl nss \ diff --git a/m4/nut_check_libsystemd.m4 b/m4/nut_check_libsystemd.m4 new file mode 100644 index 0000000000..b544c3640e --- /dev/null +++ b/m4/nut_check_libsystemd.m4 @@ -0,0 +1,90 @@ +dnl Check for LIBSYSTEMD compiler flags. On success, set nut_have_libsystemd="yes" +dnl and set LIBSYSTEMD_CFLAGS and LIBSYSTEMD_LIBS. On failure, set +dnl nut_have_libsystemd="no". This macro can be run multiple times, but will +dnl do the checking only once. + +AC_DEFUN([NUT_CHECK_LIBSYSTEMD], +[ +if test -z "${nut_have_libsystemd_seen}"; then + nut_have_libsystemd_seen=yes + NUT_CHECK_PKGCONFIG + + dnl save CFLAGS and LIBS + CFLAGS_ORIG="${CFLAGS}" + LIBS_ORIG="${LIBS}" + + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [dnl See which version of the systemd library (if any) is installed + dnl FIXME : Support detection of cflags/ldflags below by legacy + dnl discovery if pkgconfig is not there + AC_MSG_CHECKING(for libsystemd version via pkg-config) + SYSTEMD_VERSION="`$PKG_CONFIG --silence-errors --modversion libsystemd 2>/dev/null`" + if test "$?" != "0" -o -z "${SYSTEMD_VERSION}"; then + SYSTEMD_VERSION="none" + fi + AC_MSG_RESULT(${SYSTEMD_VERSION} found) + ], + [SYSTEMD_VERSION="none" + AC_MSG_NOTICE([can not check libsystemd settings via pkg-config]) + ] + ) + + AC_MSG_CHECKING(for libsystemd cflags) + AC_ARG_WITH(libsystemd-includes, + AS_HELP_STRING([@<:@--with-libsystemd-includes=CFLAGS@:>@], [include flags for the systemd library]), + [ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-libsystemd-includes - see docs/configure.txt) + ;; + *) + CFLAGS="${withval}" + ;; + esac + ], [ + dnl Not specifying a default include path here, + dnl headers are referenced by relative directory + dnl and these should be in OS location usually. + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [CFLAGS="`$PKG_CONFIG --silence-errors --cflags libsystemd 2>/dev/null`" || CFLAGS=""], + [CFLAGS=""] + )] + ) + AC_MSG_RESULT([${CFLAGS}]) + + AC_MSG_CHECKING(for libsystemd ldflags) + AC_ARG_WITH(libsystemd-libs, + AS_HELP_STRING([@<:@--with-libsystemd-libs=LIBS@:>@], [linker flags for the systemd library]), + [ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-libsystemd-libs - see docs/configure.txt) + ;; + *) + LIBS="${withval}" + ;; + esac + ], [ + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [LIBS="`$PKG_CONFIG --silence-errors --libs libsystemd 2>/dev/null`" || LIBS="-lsystemd"], + [LIBS="-lsystemd"] + )] + ) + AC_MSG_RESULT([${LIBS}]) + + dnl check if libsystemd is usable + AC_CHECK_HEADERS(systemd/sd-daemon.h, [nut_have_libsystemd=yes], [nut_have_libsystemd=no], [AC_INCLUDES_DEFAULT]) + AC_CHECK_FUNCS(sd_notify, [], [nut_have_libsystemd=no]) + + AS_IF([test x"${nut_have_libsystemd}" = x"yes"], [ + dnl Check for additional feature support in library (optional) + AC_CHECK_FUNCS(sd_booted sd_watchdog_enabled) + LIBSYSTEMD_CFLAGS="${CFLAGS}" + LIBSYSTEMD_LIBS="${LIBS}" + ]) + + dnl restore original CFLAGS and LIBS + CFLAGS="${CFLAGS_ORIG}" + LIBS="${LIBS_ORIG}" +fi +]) From f89714ae945ab9623977a60e46e9c3cfa739ec21 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 14:40:08 +0100 Subject: [PATCH 0269/1232] configure.ac, drivers/Makefile.am: use LIBI2C_LIBS to avoid pulling -li2c everywhere --- configure.ac | 6 ++++++ drivers/Makefile.am | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 1534256f3d..511478211c 100644 --- a/configure.ac +++ b/configure.ac @@ -1397,6 +1397,7 @@ dnl ---------------------------------------------------------------------- dnl checks related to --with_linux_i2c dnl Check for i2c header on Linux, used for ASEM UPS driver NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) +LIBI2C_LIBS="" if test "${nut_with_linux_i2c}" != no; then case ${target_os} in linux* ) @@ -1429,6 +1430,8 @@ if test "${nut_with_linux_i2c}" != no; then dnl "compromised" by lack of respective binary library, so dnl even if we have the right headers, ultimate link fails. dnl Note: here we keep the verdict from above, or make it worse. + LIBS_SAVED="$LIBS" + LIBS="" AC_SEARCH_LIBS([i2c_smbus_read_byte, i2c_smbus_access, i2c_smbus_read_byte_data, i2c_smbus_write_byte_datai2c_smbus_write_byte_data, i2c_smbus_read_word_data, i2c_smbus_write_word_data, i2c_smbus_read_block_data], [i2c], [nut_with_linux_i2c="yes"], @@ -1436,6 +1439,8 @@ if test "${nut_with_linux_i2c}" != no; then [AC_MSG_ERROR(i2c was required but can not be fulfilled for this build)], [nut_with_linux_i2c="no"]) ]) + LIBI2C_LIBS="$LIBS" + LIBS="$LIBS_SAVED" ;; * ) if test "${nut_with_linux_i2c}" = yes; then @@ -3345,6 +3350,7 @@ AC_SUBST(LIBMODBUS_CFLAGS) AC_SUBST(LIBMODBUS_LIBS) AC_SUBST(LIBIPMI_CFLAGS) AC_SUBST(LIBIPMI_LIBS) +AC_SUBST(LIBI2C_LIBS) AC_SUBST(DOC_BUILD_LIST) AC_SUBST(DOC_CHECK_LIST) AC_SUBST(LIBWRAP_CFLAGS) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 31fcd7120b..393845be13 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -15,6 +15,7 @@ LDADD_DRIVERS_SERIAL = libdummy_serial.la $(LDADD_DRIVERS) $(SERLIBS) # most targets are serial drivers, so make this the default LDADD = $(LDADD_DRIVERS_SERIAL) + # Avoid per-target CFLAGS, because this will prevent re-use of object # files. In any case, CFLAGS are only -I options, so there is no harm, # but only add them if we really use the target. @@ -292,9 +293,9 @@ socomec_jbus_SOURCES = socomec_jbus.c socomec_jbus_LDADD = $(LDADD_DRIVERS_SERIAL) $(LIBMODBUS_LIBS) # Linux I2C drivers -asem_LDADD = $(LDADD_DRIVERS) +asem_LDADD = $(LDADD_DRIVERS) $(LIBI2C_LIBS) asem_SOURCES = asem.c -pijuice_LDADD = $(LDADD_DRIVERS) +pijuice_LDADD = $(LDADD_DRIVERS) $(LIBI2C_LIBS) pijuice_SOURCES = pijuice.c # nutdrv_qx USB/Serial From b64957050174a552fc4e5dcf3ae2e7de23ed34c6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Jan 2023 15:24:40 +0100 Subject: [PATCH 0270/1232] common/common.c: add upsnotify() method into libcommon.la (but not libcommonclient) [#1590] --- common/Makefile.am | 16 +++ common/common.c | 253 +++++++++++++++++++++++++++++++++++++++++++++ include/common.h | 17 +++ 3 files changed, 286 insertions(+) diff --git a/common/Makefile.am b/common/Makefile.am index 9e64f050d1..4fbae5f41c 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -73,6 +73,22 @@ endif libcommon_la_LIBADD = libparseconf.la @LTLIBOBJS@ @NETLIBS@ libcommonclient_la_LIBADD = libparseconf.la @LTLIBOBJS@ @NETLIBS@ +libcommon_la_CFLAGS = $(AM_CFLAGS) +libcommonclient_la_CFLAGS = $(AM_CFLAGS) + +# Did the user request, and build env support, tighter integration with +# libsystemd methods such as sd_notify()? +if WITH_LIBSYSTEMD + libcommon_la_CFLAGS += $(LIBSYSTEMD_CFLAGS) + libcommon_la_LIBADD += $(LIBSYSTEMD_LIBS) + +# A typical client should not need this, +# but just in case (and to simplify linking)... +# libcommonclient_la_CFLAGS += $(LIBSYSTEMD_CFLAGS) +# libcommonclient_la_LIBADD += $(LIBSYSTEMD_LIBS) + libcommonclient_la_CFLAGS += -DWITHOUT_LIBSYSTEMD=1 +endif + MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, diff --git a/common/common.c b/common/common.c index 4efdfe4451..3ae0944c91 100644 --- a/common/common.c +++ b/common/common.c @@ -36,6 +36,17 @@ # include #endif +#ifdef WITH_LIBSYSTEMD +# include +/* upsnotify() debug-logs its reports; a watchdog ping is something we + * try to send often so report it just once (whether enabled or not) */ +static int upsnotify_reported_watchdog_systemd = 0; +/* Similarly for only reporting once if the notification subsystem is disabled */ +static int upsnotify_reported_disabled_systemd = 0; +#endif +/* Similarly for only reporting once if the notification subsystem is not built-in */ +static int upsnotify_reported_disabled_notech = 0; + /* the reason we define UPS_VERSION as a static string, rather than a macro, is to make dependency tracking easier (only common.o depends on nut_version_macro.h), and also to prevent all sources from @@ -591,6 +602,248 @@ const char *xbasename(const char *file) return p + 1; } +/* Send (daemon) state-change notifications to an + * external service management framework such as systemd + */ +int upsnotify(upsnotify_state_t state, const char *fmt, ...) +{ + int ret = -127; + va_list va; + char buf[LARGEBUF]; + char msgbuf[LARGEBUF]; + size_t msglen = 0; + + /* Prepare the message (if any) as a string */ + msgbuf[0] = '\0'; + if (fmt) { + va_start(va, fmt); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + /* generic message... */ + ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, va); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif + va_end(va); + + if ((ret < 0) || (ret >= (int) sizeof(msgbuf))) { + syslog(LOG_WARNING, + "%s: vsnprintf needed more than %d bytes", + __func__, LARGEBUF); + } else { + msglen = strlen(msgbuf); + } + /* Reset for actual notification processing below */ + ret = -127; + } + +#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) +# if defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD) + NUT_UNUSED_VARIABLE(buf); + NUT_UNUSED_VARIABLE(msglen); + if (!upsnotify_reported_disabled_systemd) + upsdebugx(6, "%s: notify about state %i with libsystemd: " + "skipped for libcommonclient build, " + "will not spam more about it", __func__, state); + upsnotify_reported_disabled_systemd = 1; +# else + if (!getenv("NOTIFY_SOCKET")) { + if (!upsnotify_reported_disabled_systemd) + upsdebugx(6, "%s: notify about state %i with libsystemd: " + "was requested, but not running as a service unit now, " + "will not spam more about it", + __func__, state); + upsnotify_reported_disabled_systemd = 1; + } else { +# if HAVE_SD_NOTIFY + upsdebugx(6, "%s: notify about state %i with libsystemd: use sd_notify()", __func__, state); + /* https://www.freedesktop.org/software/systemd/man/sd_notify.html */ + if (msglen) { + ret = snprintf(buf, sizeof(buf), "STATUS=%s", msgbuf); + if ((ret < 0) || (ret >= (int) sizeof(buf))) { + syslog(LOG_WARNING, + "%s: snprintf needed more than %d bytes", + __func__, LARGEBUF); + msglen = 0; + } else { + msglen = (size_t)ret; + } + } + + switch (state) { + case NOTIFY_STATE_READY: + ret = snprintf(buf + msglen, sizeof(buf) - msglen, + "%sREADY=1", + msglen ? "\n" : ""); + break; + + case NOTIFY_STATE_READY_WITH_PID: + ret = snprintf(buf + msglen, sizeof(buf) - msglen, + "%sREADY=1\n" + "MAINPID=%lu", + msglen ? "\n" : "", + (unsigned long) getpid()); + break; + + case NOTIFY_STATE_RELOADING: + ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%s%s", + msglen ? "\n" : "", + "RELOADING=1"); + break; + + case NOTIFY_STATE_STOPPING: + ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%s%s", + msglen ? "\n" : "", + "STOPPING=1"); + break; + + case NOTIFY_STATE_STATUS: + /* Only send a text message per "fmt" */ + if (!msglen) { + upsdebugx(6, "%s: failed to notify about status: none provided", __func__); + ret = -1; + } else { + ret = (int)msglen; + } + break; + + case NOTIFY_STATE_WATCHDOG: + /* Ping the framework that we are still alive */ + if (1) { /* scoping */ + int postit = 0; + +# if HAVE_SD_WATCHDOG_ENABLED + uint64_t to = 0; + postit = sd_watchdog_enabled(0, &to); + + if (postit < 0) { + if (!upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: sd_enabled_watchdog query failed: %s", + __func__, strerror(postit)); + } else { + upsdebugx(6, "%s: sd_enabled_watchdog query returned: %d " + "(%" PRIu64 "msec remain)", + __func__, postit, to); + } +# endif + + if (postit < 1) { + char *s = getenv("WATCHDOG_USEC"); + if (s && *s) { + long l = strtol(s, (char **)NULL, 10); + if (l > 0) { + pid_t wdpid = parsepid(getenv("WATCHDOG_PID")); + if (wdpid == (pid_t)-1 || wdpid == getpid()) { + postit = 1; + } else { + /* Configured, but not for this process */ + postit = 0; + } + } + } + } + + if (postit > 0) { + ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%s%s", + msglen ? "\n" : "", + "WATCHDOG=1"); + } else if (postit == 0) { + if (!upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: failed to tickle the watchdog: not enabled for this unit", __func__); + ret = -1; + } + } + break; + +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT +# pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE +# pragma GCC diagnostic ignored "-Wunreachable-code" +#endif +/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */ +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunreachable-code" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif + /* All enum cases defined as of the time of coding + * have been covered above. Handle later definitions, + * memory corruptions and buggy inputs below... + */ + default: + if (!msglen) { + upsdebugx(6, "%s: unknown state and no status message provided", __func__); + ret = -1; + } else { + upsdebugx(6, "%s: unknown state but have a status message provided", __func__); + ret = (int)msglen; + } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) ) +# pragma GCC diagnostic pop +#endif + } + + if ((ret < 0) || (ret >= (int) sizeof(buf))) { + syslog(LOG_WARNING, + "%s: snprintf needed more than %d bytes", + __func__, LARGEBUF); + ret = -1; + } else { + upsdebugx(6, "%s: posting sd_notify: %s", __func__, buf); + msglen = (size_t)ret; + ret = sd_notify(0, buf); + } + +# else /* not HAVE_SD_NOTIFY: */ + /* FIXME: Try to fork and call systemd-notify helper program */ + upsdebugx(6, "%s: notify about state %i with libsystemd: lacking sd_notify()", __func__, state); + ret = -127; +# endif /* HAVE_SD_NOTIFY */ + } +# endif /* if not WITHOUT_LIBSYSTEMD (explicit avoid) */ +#else /* not WITH_LIBSYSTEMD */ + NUT_UNUSED_VARIABLE(buf); + NUT_UNUSED_VARIABLE(msglen); +#endif /* WITH_LIBSYSTEMD */ + + if (ret < 0 +#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && HAVE_SD_NOTIFY + && !( (!upsnotify_reported_watchdog_systemd) && (state == NOTIFY_STATE_STATUS)) +#endif + ) { + if (ret == -127) { + if (!upsnotify_reported_disabled_notech) + upsdebugx(6, "%s: failed to notify about state %i: no notification tech defined, will not spam more about it", __func__, state); + upsnotify_reported_disabled_notech = 1; + } else { + upsdebugx(6, "%s: failed to notify about state %i", __func__, state); + } + } + +#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) + if (state == NOTIFY_STATE_STATUS) { + upsdebugx(6, "%s: logged the systemd watchdog situation once, will not spam more about it", __func__); + upsnotify_reported_watchdog_systemd = 1; + } +#endif + + return ret; +} + static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret; diff --git a/include/common.h b/include/common.h index 6e22e3159d..b2e61abc2d 100644 --- a/include/common.h +++ b/include/common.h @@ -245,6 +245,23 @@ const char * altpidpath(void); /* Die with a standard message if socket filename is too long */ void check_unix_socket_filename(const char *fn); +/* Send (daemon) state-change notifications to an + * external service management framework such as systemd. + * State types below are initially loosely modeled after + * https://www.freedesktop.org/software/systemd/man/sd_notify.html + */ +typedef enum eupsnotify_state { + NOTIFY_STATE_READY = 1, + NOTIFY_STATE_READY_WITH_PID, + NOTIFY_STATE_RELOADING, + NOTIFY_STATE_STOPPING, + NOTIFY_STATE_STATUS, /* Send a text message per "fmt" below */ + NOTIFY_STATE_WATCHDOG /* Ping the framework that we are still alive */ +} upsnotify_state_t; +/* Note: here fmt may be null, then the STATUS message would not be sent/added */ +int upsnotify(upsnotify_state_t state, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + /* upslog*() messages are sent to syslog always; * their life after that is out of NUT's control */ void upslog_with_errno(int priority, const char *fmt, ...) From 72459f5a6a78b95227d07a9f8e0206f5e1d2d139 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:23:43 +0100 Subject: [PATCH 0271/1232] common/common.c: parsepid(): handle NULL input reasonably on all platforms [#1590] --- common/common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 3ae0944c91..8b38bb6531 100644 --- a/common/common.c +++ b/common/common.c @@ -449,9 +449,15 @@ int sendsignalpid(pid_t pid, int sig) pid_t parsepid(const char *buf) { pid_t pid = -1; + intmax_t _pid; + + if (!buf) { + upsdebugx(6, "%s: called with NULL input", __func__); + return pid; + } /* assuming 10 digits for a long */ - intmax_t _pid = strtol(buf, (char **)NULL, 10); + _pid = strtol(buf, (char **)NULL, 10); if (_pid <= get_max_pid_t()) { pid = (pid_t)_pid; } else { From 936d2105df2c1eafb102b99d8fd6e2052dacbae7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:39:32 +0100 Subject: [PATCH 0272/1232] clients/upsmon.c: make use of new upsnotify() [#1590] --- clients/upsmon.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index f0767a5aa1..aac051e1b6 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -621,6 +621,8 @@ static void doshutdown(void) static void doshutdown(void) { + upsnotify(NOTIFY_STATE_STOPPING, "Executing automatic power-fail shutdown"); + /* this should probably go away at some point */ upslogx(LOG_CRIT, "Executing automatic power-fail shutdown"); wall("Executing automatic power-fail shutdown\n"); @@ -2580,6 +2582,7 @@ int main(int argc, char *argv[]) } if (upscli_init(certverify, certpath, certname, certpasswd) < 0) { + upsnotify(NOTIFY_STATE_STOPPING, "Failed upscli_init()"); exit(EXIT_FAILURE); } @@ -2590,15 +2593,22 @@ int main(int argc, char *argv[]) closelog(); open_syslog(prog); + upsnotify(NOTIFY_STATE_READY_WITH_PID, NULL); + while (exit_flag == 0) { utype_t *ups; + upsnotify(NOTIFY_STATE_WATCHDOG, NULL); + /* check flags from signal handlers */ if (userfsd) forceshutdown(); - if (reload_flag) + if (reload_flag) { + upsnotify(NOTIFY_STATE_RELOADING, NULL); reload_conf(); + upsnotify(NOTIFY_STATE_READY, NULL); + } for (ups = firstups; ups != NULL; ups = ups->next) pollups(ups); @@ -2676,6 +2686,7 @@ int main(int argc, char *argv[]) } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); + upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag); upsmon_cleanup(); exit(EXIT_SUCCESS); From 673a44da8642860d3e11db124a48cdc17553bda6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:45:07 +0100 Subject: [PATCH 0273/1232] clients/upslog.c: make use of new upsnotify() [#1590] --- clients/upslog.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clients/upslog.c b/clients/upslog.c index 24f96dcad9..191aedf390 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -618,7 +618,11 @@ int main(int argc, char **argv) compile_format(); + upsnotify(NOTIFY_STATE_READY_WITH_PID, NULL); + while (exit_flag == 0) { + upsnotify(NOTIFY_STATE_WATCHDOG, NULL); + time(&now); if (nextpoll > now) { @@ -631,10 +635,12 @@ int main(int argc, char **argv) } if (reopen_flag) { + upsnotify(NOTIFY_STATE_RELOADING, NULL); upslogx(LOG_INFO, "Signal %d: reopening log file", reopen_flag); reopen_log(); reopen_flag = 0; + upsnotify(NOTIFY_STATE_READY, NULL); } for (monhost_ups_current = monhost_ups_anchor; @@ -657,6 +663,8 @@ 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) { From 36721acacce5d8be75f4a3d4c09af5f7081ded5b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:48:40 +0100 Subject: [PATCH 0274/1232] server/upsd.c: make use of new upsnotify() [#1590] --- server/upsd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 138688bf47..1a87b55d61 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1083,12 +1083,16 @@ static void mainloop(void) stype_t *server; time_t now; + upsnotify(NOTIFY_STATE_WATCHDOG, NULL); + time(&now); if (reload_flag) { + upsnotify(NOTIFY_STATE_RELOADING, NULL); conf_reload(); poll_reload(); reload_flag = 0; + upsnotify(NOTIFY_STATE_READY, NULL); } /* cleanup instcmd/setvar status tracking entries if needed */ @@ -1914,12 +1918,16 @@ int main(int argc, char **argv) /* initialize SSL (keyfile must be readable by nut user) */ ssl_init(); + upsnotify(NOTIFY_STATE_READY_WITH_PID, NULL); + while (!exit_flag) { + /* Note: mainloop() calls upsnotify(NOTIFY_STATE_WATCHDOG, NULL); */ mainloop(); } - ssl_cleanup(); - upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); + upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag); + + ssl_cleanup(); return EXIT_SUCCESS; } From 0cf92b60205e74aaef790ab53aeeb24e9733af28 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:52:51 +0100 Subject: [PATCH 0275/1232] drivers/main.c: make use of new upsnotify() [#1590] --- drivers/main.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index 8f7dce69cd..6640b13e20 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -633,6 +633,10 @@ static void vartab_free(void) static void exit_cleanup(void) { + if (!dump_data) { + upsnotify(NOTIFY_STATE_STOPPING, "exit_cleanup()"); + } + free(chroot_path); free(device_path); free(user); @@ -1147,10 +1151,18 @@ int main(int argc, char **argv) writepid(pidfn); /* PID changes when backgrounding */ } + if (!dump_data) { + upsnotify(NOTIFY_STATE_READY_WITH_PID, NULL); + } + while (!exit_flag) { struct timeval timeout; + if (!dump_data) { + upsnotify(NOTIFY_STATE_WATCHDOG, NULL); + } + gettimeofday(&timeout, NULL); timeout.tv_sec += poll_interval; @@ -1175,8 +1187,10 @@ int main(int argc, char **argv) /* if we get here, the exit flag was set by a signal handler */ /* however, avoid to "pollute" data dump output! */ - if (!dump_data) + if (!dump_data) { upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); + upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag); + } exit(EXIT_SUCCESS); } From 10747abdf78aa2fdc85e8f3d9773ffb1b9d89f67 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 11:59:02 +0100 Subject: [PATCH 0276/1232] scripts/systemd/nut-server.service.in, scripts/systemd/nut-monitor.service.in: provide an Alias for convenience (upsd, upsmon) --- scripts/systemd/nut-monitor.service.in | 2 ++ scripts/systemd/nut-server.service.in | 1 + 2 files changed, 3 insertions(+) diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 4ee216e160..4ece1e9d94 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -1,5 +1,6 @@ [Unit] Description=Network UPS Tools - power device monitor and shutdown controller +# Note: do not mistake this historic misnomer for "NUT-Monitor" Python GUI client After=local-fs.target network.target nut-server.service # Note: We do not specify Requires nut-server.service because # the `upsd` daemon(s) may be running on a different machine @@ -24,3 +25,4 @@ PIDFile=@PIDPATH@/upsmon.pid [Install] WantedBy=nut.target +Alias=upsmon.service diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 5edc2d5fa4..063f6f158f 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -28,3 +28,4 @@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID [Install] WantedBy=nut.target +Alias=upsd.service From 483ad5f68f35ea340ea81b7e23c24f7858b054e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 12:08:47 +0100 Subject: [PATCH 0277/1232] configure.ac, scripts/systemd/*.in: optionally support Type=notify for upsd, upsmon and drivers [#1590] --- configure.ac | 24 ++++++++++++++++++++++++ scripts/systemd/nut-driver@.service.in | 4 ++-- scripts/systemd/nut-monitor.service.in | 3 ++- scripts/systemd/nut-server.service.in | 3 ++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 511478211c..79580360e4 100644 --- a/configure.ac +++ b/configure.ac @@ -2726,6 +2726,24 @@ AS_CASE(["${nut_with_libsystemd}"], ]) AC_MSG_RESULT(${with_libsystemd}) +AS_IF([test x"${with_libsystemd}" = xyes], [ + dnl Built with sd_notify support + SYSTEMD_DAEMON_ARGS_UPSD="-F" + SYSTEMD_DAEMON_TYPE_UPSD="notify" + SYSTEMD_DAEMON_ARGS_UPSMON="-F" + SYSTEMD_DAEMON_TYPE_UPSMON="notify" + SYSTEMD_DAEMON_ARGS_DRIVER="" + SYSTEMD_DAEMON_TYPE_DRIVER="notify" + ], [ + dnl "Usual" daemons that happen to be spawned by systemd + SYSTEMD_DAEMON_ARGS_UPSD="-F" + SYSTEMD_DAEMON_TYPE_UPSD="simple" + SYSTEMD_DAEMON_ARGS_UPSMON="-F" + SYSTEMD_DAEMON_TYPE_UPSMON="simple" + SYSTEMD_DAEMON_ARGS_DRIVER="" + SYSTEMD_DAEMON_TYPE_DRIVER="forking" + ]) + NUT_REPORT_FEATURE([build with tighter systemd support], [${with_libsystemd}], [], [WITH_LIBSYSTEMD], [Define to build with tighter systemd support (sd_notify etc)]) @@ -3359,6 +3377,12 @@ AC_SUBST(LIBLTDL_CFLAGS) AC_SUBST(LIBLTDL_LIBS) AC_SUBST(LIBSYSTEMD_CFLAGS) AC_SUBST(LIBSYSTEMD_LIBS) +AC_SUBST(SYSTEMD_DAEMON_ARGS_UPSD) +AC_SUBST(SYSTEMD_DAEMON_TYPE_UPSD) +AC_SUBST(SYSTEMD_DAEMON_ARGS_UPSMON) +AC_SUBST(SYSTEMD_DAEMON_TYPE_UPSMON) +AC_SUBST(SYSTEMD_DAEMON_ARGS_DRIVER) +AC_SUBST(SYSTEMD_DAEMON_TYPE_DRIVER) AC_SUBST(DRIVER_BUILD_LIST) AC_SUBST(DRIVER_MAN_LIST) AC_SUBST(DRIVER_MAN_LIST_PAGES) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index f3e08a4c23..a83e2e7ae0 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -41,7 +41,7 @@ PartOf=nut-driver.target Environment=NUT_IGNORE_NOWAIT=true EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N -ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl start "$NUTDEV"' +ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl stop "$NUTDEV"' # Restart really always, do not stop trying: StartLimitInterval=0 @@ -53,7 +53,7 @@ Restart=always # devices (so getting a chicken-and-egg problem for driver-upsd-driver # orderly series of initializations). More details in NUT issue #779. RestartSec=15s -Type=forking +Type=@SYSTEMD_DAEMON_TYPE_DRIVER@ # Note: If you customize the "maxstartdelay" in ups.conf or in your # NUT compilation defaults, so it exceeds the default systemd unit # startup timeout (typically 90 sec), then make sure to set a slightly diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 4ece1e9d94..4d2808601d 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -19,9 +19,10 @@ PartOf=nut.target [Service] EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N -ExecStart=@SBINDIR@/upsmon -F +ExecStart=@SBINDIR@/upsmon @SYSTEMD_DAEMON_ARGS_UPSMON@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid +Type=@SYSTEMD_DAEMON_TYPE_UPSMON@ [Install] WantedBy=nut.target diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 063f6f158f..512f626ff7 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -23,8 +23,9 @@ SyslogIdentifier=%N # Note: foreground mode "-F" by default skips writing a PID file (and # needs default Type=simple); we can use "-FF" here to create the file # anyway, so that old "upsd -c reload" works rather than systemd action: -ExecStart=@SBINDIR@/upsd -F +ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID +Type=@SYSTEMD_DAEMON_TYPE_UPSD@ [Install] WantedBy=nut.target From f165d611516a6aafab574b4130779687bfaed1a6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 13:21:43 +0100 Subject: [PATCH 0278/1232] NEWS, UPGRADING: cosmetic fixes --- NEWS | 12 ++++++------ UPGRADING | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index a640603a71..0108f91d2c 100644 --- a/NEWS +++ b/NEWS @@ -155,30 +155,30 @@ https://github.com/networkupstools/nut/milestone/8 this variable unless troubleshooting, although other systems rely on it) [#805] - - the nut-scanner program was updated to fall back to loading unresolved + - The nut-scanner program was updated to fall back to loading unresolved library filenames, hoping that `lt_dlopen()` implementation on the current platform would find library files better [#805] - - detection of `libltdl` in `configure` script updated with fallback code to + - Detection of `libltdl` in `configure` script updated with fallback code to find it on systems that deliver the library to `/usr/local/lib` (e.g. on FreeBSD) [#1577] - - an explicit `configure --with-nut-scanner` toggle was added, specifically + - An explicit `configure --with-nut-scanner` toggle was added, specifically so that build environments requesting `--with-all` but lack `libltdl` would abort and require either to install the dependency or explicitly forfeit the tool (some distro packages missed it quietly in the past) [#1560] - - existing openssl-1.1.0 support added for NUT v2.8.0 release was tested to + - Existing openssl-1.1.0 support added for NUT v2.8.0 release was tested to be sufficient without deprecation warnings for builds against openssl-3.0.x (but no real-time testing was done yet) [#1547] - upslog: Added support for logging multiple devices with one call to the program [#1604] - - some fixes applied to Solaris/illumos packaging and SMF service support + - Some fixes applied to Solaris/illumos packaging and SMF service support [#1554, #1564] - - some fixes for builds on older OSes with less functional default system + - Some fixes for builds on older OSes with less functional default system shell interpreters - now `autogen.sh` supports a `CONFIG_SHELL` envvar to inject its value into generated `configure` script [#1736] * Note that you may have to install additional tools (possibly from diff --git a/UPGRADING b/UPGRADING index f3c363258a..77aa6741e4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -47,7 +47,7 @@ Changes from 2.8.0 to 2.8.1 serial drivers in respective Makefile and configure script options - this may impact packaging decisions on some distributions going forward [#1446] -- an explicit `configure --with-nut-scanner` toggle was added, specifically +- An explicit `configure --with-nut-scanner` toggle was added, specifically so that build environments requesting `--with-all` but lacking `libltdl` would abort and require the packager either to install the dependency or explicitly forfeit building the tool (some distro packages missed it From 65799367c42d8acaa79b12b5ac24acfc86d448bf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 13:28:51 +0100 Subject: [PATCH 0279/1232] NEWS, UPGRADING: added libsystemd notification support [#1590] --- NEWS | 3 +++ UPGRADING | 7 +++++++ docs/nut.dict | 4 +++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0108f91d2c..b26ff0040c 100644 --- a/NEWS +++ b/NEWS @@ -222,6 +222,9 @@ https://github.com/networkupstools/nut/milestone/8 encouraged to pick optimal location for their distributions (which remains mounted at least read-only late in shutdown) [#529] + - Extended Linux systemd support with optional notifications about daemon + state (READY, RELOADING, STOPPING) and watchdog keep-alive messages [#1590] + - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, `time_t` etc.) in third-party client code that earlier sufficed to only diff --git a/UPGRADING b/UPGRADING index 77aa6741e4..027a552fc3 100644 --- a/UPGRADING +++ b/UPGRADING @@ -66,6 +66,13 @@ Changes from 2.8.0 to 2.8.1 * Several other issues have been fixed related to this file and its content, including #1030, #1037, #1117 and #1712 +- Extended Linux systemd support with optional notifications about daemon + state (READY, RELOADING, STOPPING) and watchdog keep-alive messages. + Note that `WatchdogSec=` values are currently NOT pre-set into systemd + unit file templates provided by NUT, this is an exercise for end-users + based on sizing of their deployments and performance of monitoring station + [#1590, #1777] + - snmp-ups: some subdrivers (addressed using the driver parameter `mibs`) were renamed: `pw` is now `eaton_pw_nm2`, and `pxgx_ups` is `eaton_pxg_ups` [#1715] diff --git a/docs/nut.dict b/docs/nut.dict index bd1fd31a52..0f89a7b016 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3067 utf-8 +personal_ws-1.1 en 3069 utf-8 AAS ABI ACFAIL @@ -1341,6 +1341,7 @@ WS WSE WTU Waldie +WatchdogSec Werror Wextra WhizBang @@ -2133,6 +2134,7 @@ libregex libs libsnmp libssl +libsystemd libtool libupsclient libusb From 2fcb6f3120d73a4c96074705164b1d03aac38eb8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 13:39:21 +0100 Subject: [PATCH 0280/1232] Suggest default systemd watchdog settings for upsd, upsmon and drivers [#1590] --- configure.ac | 14 ++++++++++++++ scripts/systemd/nut-driver@.service.in | 7 +++++++ scripts/systemd/nut-monitor.service.in | 1 + scripts/systemd/nut-server.service.in | 1 + 4 files changed, 23 insertions(+) diff --git a/configure.ac b/configure.ac index 79580360e4..427eab43a4 100644 --- a/configure.ac +++ b/configure.ac @@ -2734,6 +2734,13 @@ AS_IF([test x"${with_libsystemd}" = xyes], [ SYSTEMD_DAEMON_TYPE_UPSMON="notify" SYSTEMD_DAEMON_ARGS_DRIVER="" SYSTEMD_DAEMON_TYPE_DRIVER="notify" + dnl Note: at this time we do not pre-define watchdog settings, + dnl to avoid breaking something by a poorly hardcoded guess. + dnl This is something end-users should do for their deployment, + dnl especially for drivers + SYSTEMD_DAEMON_WATCHDOG_DRIVER="#WatchdogSec=240s" + SYSTEMD_DAEMON_WATCHDOG_UPSD="#WatchdogSec=240s" + SYSTEMD_DAEMON_WATCHDOG_UPSMON="#WatchdogSec=240s" ], [ dnl "Usual" daemons that happen to be spawned by systemd SYSTEMD_DAEMON_ARGS_UPSD="-F" @@ -2742,6 +2749,10 @@ AS_IF([test x"${with_libsystemd}" = xyes], [ SYSTEMD_DAEMON_TYPE_UPSMON="simple" SYSTEMD_DAEMON_ARGS_DRIVER="" SYSTEMD_DAEMON_TYPE_DRIVER="forking" + dnl Watchdog should not be configured for not-notifying units, right? + SYSTEMD_DAEMON_WATCHDOG_DRIVER="#WatchdogSec=240s" + SYSTEMD_DAEMON_WATCHDOG_UPSD="#WatchdogSec=240s" + SYSTEMD_DAEMON_WATCHDOG_UPSMON="#WatchdogSec=240s" ]) NUT_REPORT_FEATURE([build with tighter systemd support], [${with_libsystemd}], [], @@ -3383,6 +3394,9 @@ AC_SUBST(SYSTEMD_DAEMON_ARGS_UPSMON) AC_SUBST(SYSTEMD_DAEMON_TYPE_UPSMON) AC_SUBST(SYSTEMD_DAEMON_ARGS_DRIVER) AC_SUBST(SYSTEMD_DAEMON_TYPE_DRIVER) +AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSD) +AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSMON) +AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_DRIVER) AC_SUBST(DRIVER_BUILD_LIST) AC_SUBST(DRIVER_MAN_LIST) AC_SUBST(DRIVER_MAN_LIST_PAGES) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index a83e2e7ae0..d5272a9559 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -54,6 +54,13 @@ Restart=always # orderly series of initializations). More details in NUT issue #779. RestartSec=15s Type=@SYSTEMD_DAEMON_TYPE_DRIVER@ +# Note: if you set up with systemd notification support, you can take +# advantage of watchdog mechanism. Timeouts involved are deployment +# dependent (how many devices you monitor, how stressed are they and +# the monitoring system, protocol used -- e.g. SNMP walks can take long), +# so distributions should not pre-define this (at least not to a small +# value): +@SYSTEMD_DAEMON_WATCHDOG_DRIVER@ # Note: If you customize the "maxstartdelay" in ups.conf or in your # NUT compilation defaults, so it exceeds the default systemd unit # startup timeout (typically 90 sec), then make sure to set a slightly diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 4d2808601d..a51ec89fdb 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -23,6 +23,7 @@ ExecStart=@SBINDIR@/upsmon @SYSTEMD_DAEMON_ARGS_UPSMON@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid Type=@SYSTEMD_DAEMON_TYPE_UPSMON@ +@SYSTEMD_DAEMON_WATCHDOG_UPSMON@ [Install] WantedBy=nut.target diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 512f626ff7..62eb8e3aba 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -26,6 +26,7 @@ SyslogIdentifier=%N ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID Type=@SYSTEMD_DAEMON_TYPE_UPSD@ +@SYSTEMD_DAEMON_WATCHDOG_UPSD@ [Install] WantedBy=nut.target From 34f8cc77a3876f3e809bf1bcd1fe29cb53c74223 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 13:47:25 +0100 Subject: [PATCH 0281/1232] configure.ac: comment a TODO: consider calling "systemd-notify" if have no sd_notify() [#1590] --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 427eab43a4..5dadf3e1bd 100644 --- a/configure.ac +++ b/configure.ac @@ -2712,6 +2712,9 @@ fi dnl Note: we may want binaries with sd_notify and similar features regardless dnl of building and delivering unit files (which may be crafted separately). +dnl TODO: although end-user deployments (for custom builds) may be lacking +dnl libsystemd development files, they might have a `systemd-notify` program +dnl intended to help scripted service units. Consider making use of that then. AC_MSG_CHECKING(whether to build binaries with tighter systemd integration support) NUT_ARG_WITH([libsystemd], [build binaries with tighter systemd integration (notifications etc)], [auto]) NUT_CHECK_LIBSYSTEMD From 08e14a169546f5e0ffcc3f20c48293da74a95fb7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 15:24:32 +0100 Subject: [PATCH 0282/1232] common/common.c: upsnotify(): revise "snprintf needed more than..." messages [#1590] --- common/common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/common.c b/common/common.c index 8b38bb6531..4522c566a8 100644 --- a/common/common.c +++ b/common/common.c @@ -641,8 +641,8 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if ((ret < 0) || (ret >= (int) sizeof(msgbuf))) { syslog(LOG_WARNING, - "%s: vsnprintf needed more than %d bytes", - __func__, LARGEBUF); + "%s (%s:%d): vsnprintf needed more than %" PRIuSIZE " bytes: %d", + __func__, __FILE__, __LINE__, sizeof(msgbuf), ret); } else { msglen = strlen(msgbuf); } @@ -675,8 +675,8 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) ret = snprintf(buf, sizeof(buf), "STATUS=%s", msgbuf); if ((ret < 0) || (ret >= (int) sizeof(buf))) { syslog(LOG_WARNING, - "%s: snprintf needed more than %d bytes", - __func__, LARGEBUF); + "%s (%s:%d): snprintf needed more than %" PRIuSIZE " bytes: %d", + __func__, __FILE__, __LINE__, sizeof(buf), ret); msglen = 0; } else { msglen = (size_t)ret; @@ -805,8 +805,8 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if ((ret < 0) || (ret >= (int) sizeof(buf))) { syslog(LOG_WARNING, - "%s: snprintf needed more than %d bytes", - __func__, LARGEBUF); + "%s (%s:%d): snprintf needed more than %" PRIuSIZE " bytes: %d", + __func__, __FILE__, __LINE__, sizeof(buf), ret); ret = -1; } else { upsdebugx(6, "%s: posting sd_notify: %s", __func__, buf); From d2c01233a42dcb5b84eff89b792f26f42331beb4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 18:07:21 +0100 Subject: [PATCH 0283/1232] Suggest default systemd NotifyAccess settings for upsd, upsmon and drivers [#1590] --- configure.ac | 14 ++++++++++++++ scripts/systemd/nut-driver@.service.in | 1 + scripts/systemd/nut-monitor.service.in | 1 + scripts/systemd/nut-server.service.in | 1 + 4 files changed, 17 insertions(+) diff --git a/configure.ac b/configure.ac index 5dadf3e1bd..4691c7dc99 100644 --- a/configure.ac +++ b/configure.ac @@ -2737,6 +2737,14 @@ AS_IF([test x"${with_libsystemd}" = xyes], [ SYSTEMD_DAEMON_TYPE_UPSMON="notify" SYSTEMD_DAEMON_ARGS_DRIVER="" SYSTEMD_DAEMON_TYPE_DRIVER="notify" + dnl Calling shell, upsdrvctl, driver, and then it forks... ugh! + dnl https://github.com/systemd/systemd/issues/25961 + dnl FIXME: if NotifyAccess=cgroup appears, use it (consult SYSTEMD_VERSION) + SYSTEMD_DAEMON_NOTIFYACCESS_DRIVER="NotifyAccess=all" + dnl Similar for UPSMON with its two processes: + SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON="NotifyAccess=all" + dnl UPSD is started directly by systemd and do not fork: + SYSTEMD_DAEMON_NOTIFYACCESS_UPSD="NotifyAccess=main" dnl Note: at this time we do not pre-define watchdog settings, dnl to avoid breaking something by a poorly hardcoded guess. dnl This is something end-users should do for their deployment, @@ -2752,6 +2760,9 @@ AS_IF([test x"${with_libsystemd}" = xyes], [ SYSTEMD_DAEMON_TYPE_UPSMON="simple" SYSTEMD_DAEMON_ARGS_DRIVER="" SYSTEMD_DAEMON_TYPE_DRIVER="forking" + SYSTEMD_DAEMON_NOTIFYACCESS_DRIVER="" + SYSTEMD_DAEMON_NOTIFYACCESS_UPSD="" + SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON="" dnl Watchdog should not be configured for not-notifying units, right? SYSTEMD_DAEMON_WATCHDOG_DRIVER="#WatchdogSec=240s" SYSTEMD_DAEMON_WATCHDOG_UPSD="#WatchdogSec=240s" @@ -3397,6 +3408,9 @@ AC_SUBST(SYSTEMD_DAEMON_ARGS_UPSMON) AC_SUBST(SYSTEMD_DAEMON_TYPE_UPSMON) AC_SUBST(SYSTEMD_DAEMON_ARGS_DRIVER) AC_SUBST(SYSTEMD_DAEMON_TYPE_DRIVER) +AC_SUBST(SYSTEMD_DAEMON_NOTIFYACCESS_DRIVER) +AC_SUBST(SYSTEMD_DAEMON_NOTIFYACCESS_UPSD) +AC_SUBST(SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSD) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSMON) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_DRIVER) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index d5272a9559..413750813a 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -54,6 +54,7 @@ Restart=always # orderly series of initializations). More details in NUT issue #779. RestartSec=15s Type=@SYSTEMD_DAEMON_TYPE_DRIVER@ +@SYSTEMD_DAEMON_NOTIFYACCESS_DRIVER@ # Note: if you set up with systemd notification support, you can take # advantage of watchdog mechanism. Timeouts involved are deployment # dependent (how many devices you monitor, how stressed are they and diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index a51ec89fdb..210c7c2998 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -24,6 +24,7 @@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid Type=@SYSTEMD_DAEMON_TYPE_UPSMON@ @SYSTEMD_DAEMON_WATCHDOG_UPSMON@ +@SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON@ [Install] WantedBy=nut.target diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 62eb8e3aba..e47c7b0846 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -27,6 +27,7 @@ ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID Type=@SYSTEMD_DAEMON_TYPE_UPSD@ @SYSTEMD_DAEMON_WATCHDOG_UPSD@ +@SYSTEMD_DAEMON_NOTIFYACCESS_UPSD@ [Install] WantedBy=nut.target From c3707d6b54dc636b772078221997590f8bb0ee66 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 18:09:38 +0100 Subject: [PATCH 0284/1232] common/common.c: upsnotify(): hush watchdog-related logging further [#1590] --- common/common.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/common/common.c b/common/common.c index 4522c566a8..bfa0aab4e8 100644 --- a/common/common.c +++ b/common/common.c @@ -669,7 +669,9 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) upsnotify_reported_disabled_systemd = 1; } else { # if HAVE_SD_NOTIFY - upsdebugx(6, "%s: notify about state %i with libsystemd: use sd_notify()", __func__, state); + if (state != NOTIFY_STATE_WATCHDOG || !upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: notify about state %i with libsystemd: use sd_notify()", __func__, state); + /* https://www.freedesktop.org/software/systemd/man/sd_notify.html */ if (msglen) { ret = snprintf(buf, sizeof(buf), "STATUS=%s", msgbuf); @@ -734,9 +736,10 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) upsdebugx(6, "%s: sd_enabled_watchdog query failed: %s", __func__, strerror(postit)); } else { - upsdebugx(6, "%s: sd_enabled_watchdog query returned: %d " - "(%" PRIu64 "msec remain)", - __func__, postit, to); + if (!upsnotify_reported_watchdog_systemd || postit > 0) + upsdebugx(6, "%s: sd_enabled_watchdog query returned: %d " + "(%" PRIu64 "msec remain)", + __func__, postit, to); } # endif @@ -763,7 +766,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) } else if (postit == 0) { if (!upsnotify_reported_watchdog_systemd) upsdebugx(6, "%s: failed to tickle the watchdog: not enabled for this unit", __func__); - ret = -1; + ret = -126; } } break; @@ -804,9 +807,12 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) } if ((ret < 0) || (ret >= (int) sizeof(buf))) { - syslog(LOG_WARNING, - "%s (%s:%d): snprintf needed more than %" PRIuSIZE " bytes: %d", - __func__, __FILE__, __LINE__, sizeof(buf), ret); + /* Refusal to send the watchdog ping is not an error to report */ + if ( !(ret == -126 && (state == NOTIFY_STATE_WATCHDOG)) ) { + syslog(LOG_WARNING, + "%s (%s:%d): snprintf needed more than %" PRIuSIZE " bytes: %d", + __func__, __FILE__, __LINE__, sizeof(buf), ret); + } ret = -1; } else { upsdebugx(6, "%s: posting sd_notify: %s", __func__, buf); @@ -828,7 +834,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (ret < 0 #if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && HAVE_SD_NOTIFY - && !( (!upsnotify_reported_watchdog_systemd) && (state == NOTIFY_STATE_STATUS)) + && (!upsnotify_reported_watchdog_systemd || (state != NOTIFY_STATE_WATCHDOG)) #endif ) { if (ret == -127) { @@ -841,7 +847,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) } #if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) - if (state == NOTIFY_STATE_STATUS) { + if (state == NOTIFY_STATE_WATCHDOG && !upsnotify_reported_watchdog_systemd) { upsdebugx(6, "%s: logged the systemd watchdog situation once, will not spam more about it", __func__); upsnotify_reported_watchdog_systemd = 1; } From 6b62728a7027b59e57371055705815e935223a25 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 18:10:02 +0100 Subject: [PATCH 0285/1232] common/common.c: upsnotify(): log setting MAINPID [#1590] --- common/common.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/common.c b/common/common.c index bfa0aab4e8..5ee17fb5d2 100644 --- a/common/common.c +++ b/common/common.c @@ -698,6 +698,13 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) "MAINPID=%lu", msglen ? "\n" : "", (unsigned long) getpid()); + upsdebugx(6, "%s: notifying systemd about MAINPID=%lu", + __func__, (unsigned long) getpid()); + /* could be a great moment to call reset_cached_pid() to + * un-wedge sd_enabled_watchdog() for NUT drivers, but + * it is not public API. See more at: + * https://github.com/systemd/systemd/issues/25961 + */ break; case NOTIFY_STATE_RELOADING: From 1ff2f9322e73d0db0ce398c409c5d10a9b5ba452 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 18:11:26 +0100 Subject: [PATCH 0286/1232] common/common.c: upsnotify(): log checking "WATCHDOG_USEC" and "WATCHDOG_PID" (once) [#1590] --- common/common.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 5ee17fb5d2..fe5449ed5f 100644 --- a/common/common.c +++ b/common/common.c @@ -752,14 +752,23 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (postit < 1) { char *s = getenv("WATCHDOG_USEC"); + if (!upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: WATCHDOG_USEC=%s", __func__, s); if (s && *s) { long l = strtol(s, (char **)NULL, 10); if (l > 0) { pid_t wdpid = parsepid(getenv("WATCHDOG_PID")); if (wdpid == (pid_t)-1 || wdpid == getpid()) { + if (!upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: can post: WATCHDOG_PID=%li", + __func__, (long)wdpid); postit = 1; } else { - /* Configured, but not for this process */ + if (!upsnotify_reported_watchdog_systemd) + upsdebugx(6, "%s: watchdog is configured, " + "but not for this process: " + "WATCHDOG_PID=%li", + __func__, (long)wdpid); postit = 0; } } From 497bacf514b8dacb77c79b897b58d39be7fd7840 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Jan 2023 18:13:05 +0100 Subject: [PATCH 0287/1232] common/common.c: upsnotify(): opportunistically post sd_notify() even if "WATCHDOG_PID" mismatches [#1590] --- common/common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index fe5449ed5f..4db0e0e875 100644 --- a/common/common.c +++ b/common/common.c @@ -769,7 +769,10 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) "but not for this process: " "WATCHDOG_PID=%li", __func__, (long)wdpid); - postit = 0; + /* Currently just try to post - at worst, systemd + * NotifyAccess will prohibit the message */ + /* postit = 0; */ + postit = 1; } } } From 14a2867344e9636f9607df6e394c069c3ab570c7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 19:14:47 +0100 Subject: [PATCH 0288/1232] scripts/systemd/nut-server.service.in, scripts/systemd/nut-monitor.service.in: use Restart=on-failure so that clean intentional exit (e.g. by signal handling) does not revive it [#1781] --- scripts/systemd/nut-monitor.service.in | 5 +++++ scripts/systemd/nut-server.service.in | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 210c7c2998..5b22148ae8 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -22,6 +22,11 @@ SyslogIdentifier=%N ExecStart=@SBINDIR@/upsmon @SYSTEMD_DAEMON_ARGS_UPSMON@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid +# If "-FF" or background-daemon mode is used, so that PID file exists +# and "upsmon -c stop" in particular can be used from command-line or +# legacy scripts, it causes a clean and intentional exit of the daemon. +# Then systemd should not revive it - hence restart it only on failure: +Restart=on-failure Type=@SYSTEMD_DAEMON_TYPE_UPSMON@ @SYSTEMD_DAEMON_WATCHDOG_UPSMON@ @SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON@ diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index e47c7b0846..0a377c23ab 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -25,6 +25,13 @@ SyslogIdentifier=%N # anyway, so that old "upsd -c reload" works rather than systemd action: ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID +# No tracking for PIDFile path and service attribute here (it might not +# even exist). +# If "-FF" or background-daemon mode is used, so that PID file exists +# and "upsd -c stop" in particular can be used from command-line or +# legacy scripts, it causes a clean and intentional exit of the daemon. +# Then systemd should not revive it - hence restart it only on failure: +Restart=on-failure Type=@SYSTEMD_DAEMON_TYPE_UPSD@ @SYSTEMD_DAEMON_WATCHDOG_UPSD@ @SYSTEMD_DAEMON_NOTIFYACCESS_UPSD@ From 81453b6d62fc33e6075a9bdbdfef7a5b3cf5f078 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 19:16:44 +0100 Subject: [PATCH 0289/1232] configure.ac: run systemd/nut-server.service both with a PID file and without forking [#1781] --- configure.ac | 4 +++- docs/man/upsd.txt | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4691c7dc99..0bd0f1af6d 100644 --- a/configure.ac +++ b/configure.ac @@ -2731,7 +2731,9 @@ AC_MSG_RESULT(${with_libsystemd}) AS_IF([test x"${with_libsystemd}" = xyes], [ dnl Built with sd_notify support - SYSTEMD_DAEMON_ARGS_UPSD="-F" + dnl Note: `upsd -FF` both runs without forking and leaves a PID file, as + dnl needed for `upsd -c reload` in legacy scripts and old habits to work: + SYSTEMD_DAEMON_ARGS_UPSD="-FF" SYSTEMD_DAEMON_TYPE_UPSD="notify" SYSTEMD_DAEMON_ARGS_UPSMON="-F" SYSTEMD_DAEMON_TYPE_UPSMON="notify" diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index ffdcbcc802..fd3843c5ac 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -89,8 +89,8 @@ upsd can reload its configuration files without shutting down the process if you send it a SIGHUP or start it again with `-c reload`. This only works if the background process is able to read those files, and if the daemon did save a PID file when it started (e.g. service instances wrapped by systemd -or SMF do not save them by default -- use respective `reload`/`refresh` -framework actions instead). +or SMF might not save them by default -- use respective `reload`/`refresh` +framework actions instead then). If you think that upsd can't reload, check your syslog for error messages. If it's complaining about not being able to read the files, then you need From a074622f53a461712f7a6595dfc88bde4bc7f11c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 19:19:00 +0100 Subject: [PATCH 0290/1232] common/common.c, m4/nut_check_libsystemd.m4: use sd_notify_barrier() if available after reporting MAINPID to systemd [#1590] --- common/common.c | 11 +++++++++++ m4/nut_check_libsystemd.m4 | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 4db0e0e875..f88f17511a 100644 --- a/common/common.c +++ b/common/common.c @@ -837,6 +837,17 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) upsdebugx(6, "%s: posting sd_notify: %s", __func__, buf); msglen = (size_t)ret; ret = sd_notify(0, buf); + if (ret > 0 && state == NOTIFY_STATE_READY_WITH_PID) { + /* Usually we begin the main loop just after this + * and post a watchdog message but systemd did not + * yet prepare to handle us */ + upsdebugx(6, "%s: wait for NOTIFY_STATE_READY_WITH_PID to be handled by systemd", __func__); +# if HAVE_SD_NOTIFY_BARRIER + sd_notify_barrier(0, UINT64_MAX); +# else + usleep(3 * 1000000); +# endif + } } # else /* not HAVE_SD_NOTIFY: */ diff --git a/m4/nut_check_libsystemd.m4 b/m4/nut_check_libsystemd.m4 index b544c3640e..155add4423 100644 --- a/m4/nut_check_libsystemd.m4 +++ b/m4/nut_check_libsystemd.m4 @@ -78,7 +78,7 @@ if test -z "${nut_have_libsystemd_seen}"; then AS_IF([test x"${nut_have_libsystemd}" = x"yes"], [ dnl Check for additional feature support in library (optional) - AC_CHECK_FUNCS(sd_booted sd_watchdog_enabled) + AC_CHECK_FUNCS(sd_booted sd_watchdog_enabled sd_notify_barrier) LIBSYSTEMD_CFLAGS="${CFLAGS}" LIBSYSTEMD_LIBS="${LIBS}" ]) From 391bf52ed1b9844978414d35a97d1f3b38c87088 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 19:38:26 +0100 Subject: [PATCH 0291/1232] common/common.c: set WATCHDOG_PID along with MAINPID and re-enable not-posting the pings if expected PID is not ours [#1590] --- common/common.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/common/common.c b/common/common.c index f88f17511a..860435c594 100644 --- a/common/common.c +++ b/common/common.c @@ -693,18 +693,35 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) break; case NOTIFY_STATE_READY_WITH_PID: - ret = snprintf(buf + msglen, sizeof(buf) - msglen, - "%sREADY=1\n" - "MAINPID=%lu", - msglen ? "\n" : "", - (unsigned long) getpid()); - upsdebugx(6, "%s: notifying systemd about MAINPID=%lu", - __func__, (unsigned long) getpid()); - /* could be a great moment to call reset_cached_pid() to - * un-wedge sd_enabled_watchdog() for NUT drivers, but - * it is not public API. See more at: - * https://github.com/systemd/systemd/issues/25961 - */ + if (1) { /* scoping */ + char pidbuf[SMALLBUF]; + if (snprintf(pidbuf, sizeof(pidbuf), "%lu", (unsigned long) getpid())) { + ret = snprintf(buf + msglen, sizeof(buf) - msglen, + "%sREADY=1\n" + "MAINPID=%s", + msglen ? "\n" : "", + pidbuf); + upsdebugx(6, "%s: notifying systemd about MAINPID=%s", + __func__, pidbuf); + /* https://github.com/systemd/systemd/issues/25961 + * Reset the WATCHDOG_PID so we know this is the + * process we want to post pings from! + */ + unsetenv("WATCHDOG_PID"); + setenv("WATCHDOG_PID", pidbuf, 1); + } else { + upsdebugx(6, "%s: NOT notifying systemd about MAINPID, " + "got an error stringifying it; processing as " + "plain NOTIFY_STATE_READY", + __func__); + ret = snprintf(buf + msglen, sizeof(buf) - msglen, + "%sREADY=1", + msglen ? "\n" : ""); + /* TODO: Maybe revise/drop this tweak if + * loggers other than systemd are used: */ + state = NOTIFY_STATE_READY; + } + } break; case NOTIFY_STATE_RELOADING: @@ -769,10 +786,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) "but not for this process: " "WATCHDOG_PID=%li", __func__, (long)wdpid); - /* Currently just try to post - at worst, systemd - * NotifyAccess will prohibit the message */ - /* postit = 0; */ - postit = 1; + postit = 0; } } } From aafc8b44713058cb11e7a6a1eb9a815ab3e83d7d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 19:52:21 +0100 Subject: [PATCH 0292/1232] common/common.c: optionally define DEBUG_SYSTEMD_WATCHDOG to ignore upsnotify_reported_watchdog_systemd hush-flag when troubleshooting [#1590] --- common/common.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/common/common.c b/common/common.c index 860435c594..9a82a69402 100644 --- a/common/common.c +++ b/common/common.c @@ -43,6 +43,11 @@ static int upsnotify_reported_watchdog_systemd = 0; /* Similarly for only reporting once if the notification subsystem is disabled */ static int upsnotify_reported_disabled_systemd = 0; +# ifndef DEBUG_SYSTEMD_WATCHDOG +/* Define this to 1 for lots of spam at debug level 6, and ignoring WATCHDOG_PID + * so trying to post reports anyway if WATCHDOG_USEC is valid */ +# define DEBUG_SYSTEMD_WATCHDOG 0 +# endif #endif /* Similarly for only reporting once if the notification subsystem is not built-in */ static int upsnotify_reported_disabled_notech = 0; @@ -669,7 +674,10 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) upsnotify_reported_disabled_systemd = 1; } else { # if HAVE_SD_NOTIFY + +# if ! DEBUG_SYSTEMD_WATCHDOG if (state != NOTIFY_STATE_WATCHDOG || !upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: notify about state %i with libsystemd: use sd_notify()", __func__, state); /* https://www.freedesktop.org/software/systemd/man/sd_notify.html */ @@ -756,11 +764,17 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) postit = sd_watchdog_enabled(0, &to); if (postit < 0) { +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: sd_enabled_watchdog query failed: %s", __func__, strerror(postit)); } else { +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd || postit > 0) +# else + if (postit > 0) +# endif upsdebugx(6, "%s: sd_enabled_watchdog query returned: %d " "(%" PRIu64 "msec remain)", __func__, postit, to); @@ -769,24 +783,41 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (postit < 1) { char *s = getenv("WATCHDOG_USEC"); +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: WATCHDOG_USEC=%s", __func__, s); if (s && *s) { long l = strtol(s, (char **)NULL, 10); if (l > 0) { pid_t wdpid = parsepid(getenv("WATCHDOG_PID")); if (wdpid == (pid_t)-1 || wdpid == getpid()) { +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: can post: WATCHDOG_PID=%li", __func__, (long)wdpid); postit = 1; } else { +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: watchdog is configured, " "but not for this process: " "WATCHDOG_PID=%li", __func__, (long)wdpid); +# if DEBUG_SYSTEMD_WATCHDOG + /* Just try to post - at worst, systemd + * NotifyAccess will prohibit the message. + * The envvar simply helps child processes + * know they should not spam the watchdog + * handler (usually only MAINPID should): + * https://github.com/systemd/systemd/issues/25961#issuecomment-1373947907 + */ + postit = 1; +# else postit = 0; +# endif } } } @@ -797,7 +828,9 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) msglen ? "\n" : "", "WATCHDOG=1"); } else if (postit == 0) { +# if ! DEBUG_SYSTEMD_WATCHDOG if (!upsnotify_reported_watchdog_systemd) +# endif upsdebugx(6, "%s: failed to tickle the watchdog: not enabled for this unit", __func__); ret = -126; } @@ -878,7 +911,9 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (ret < 0 #if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && HAVE_SD_NOTIFY +# if ! DEBUG_SYSTEMD_WATCHDOG && (!upsnotify_reported_watchdog_systemd || (state != NOTIFY_STATE_WATCHDOG)) +# endif #endif ) { if (ret == -127) { @@ -891,10 +926,12 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) } #if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) +# if ! DEBUG_SYSTEMD_WATCHDOG if (state == NOTIFY_STATE_WATCHDOG && !upsnotify_reported_watchdog_systemd) { upsdebugx(6, "%s: logged the systemd watchdog situation once, will not spam more about it", __func__); upsnotify_reported_watchdog_systemd = 1; } +# endif #endif return ret; From ca057d515ffcb957ac579d6f3e45019eae9dc89d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 20:00:48 +0100 Subject: [PATCH 0293/1232] docs/configure.txt: document --with-libsystemd related options [#1590] --- docs/configure.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 488e7225eb..822fca1990 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -537,6 +537,18 @@ Use `--with-systemdtmpfilesdir` to detect the settings using pkg-config. Use `--with-systemdtmpfilesdir=no` to disable this feature altogether. + --with-libsystemd=(auto|yes|no) + --with-libsystemd-includes=CFLAGS + --with-libsystemd-libs=LDFLAGS + +If the build system provides `libsystemd` headers, NUT binaries can be +built with tighter integration to this service management framework. +In this case NUT daemons (`upsd`, `upsmon`, `upslog` and drivers) would +report their life-cycle milestones (`READY`, `RELOADING`, `STOPPING`) and +support the watchdog reports (if enabled in their respective units by +end-user -- not done by default since the numbers depends on monitoring +system performance). Default: "auto" (integration enabled if detected). + --with-augeas-lenses-dir=PATH Where to install Augeas configuration-management lenses. From d78995224e80b3ec71b1ffaea14cb22958550f91 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 20:13:36 +0100 Subject: [PATCH 0294/1232] fixup! scripts/systemd/nut-server.service.in, scripts/systemd/nut-monitor.service.in: provide an Alias for convenience (upsd, upsmon) --- NEWS | 4 ++++ docs/FAQ.txt | 4 ++++ docs/config-notes.txt | 4 ++++ docs/man/upsd.txt | 15 ++++++++++++--- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index b26ff0040c..e3dfa9b151 100644 --- a/NEWS +++ b/NEWS @@ -225,6 +225,10 @@ https://github.com/networkupstools/nut/milestone/8 - Extended Linux systemd support with optional notifications about daemon state (READY, RELOADING, STOPPING) and watchdog keep-alive messages [#1590] + - Extended Linux systemd units with aliases named after the daemons: + `nut-server.service` as `upsd.service`, and `nut-monitor.service` as + `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, `time_t` etc.) in third-party client code that earlier sufficed to only diff --git a/docs/FAQ.txt b/docs/FAQ.txt index d8e24baceb..2666478d97 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -550,6 +550,10 @@ of `nut-server.service` by default starts `upsd -F` and does not save a PID file; if your workflow requires to use plain `upsd -c reload`, you should customize the unit (with a drop-in file) to start `upsd -FF`. +NUT releases after 2.8.0 define aliases for these units, so if your Linux +distribution uses NUT-provided unit definitions, `systemctl reload upsd` +may also work. + == I just bought a new WhizBang UPS that has a USB connector. How do I monitor it? There are several driver to support USB models. diff --git a/docs/config-notes.txt b/docs/config-notes.txt index 2e0ab75e02..5f9f7a236d 100644 --- a/docs/config-notes.txt +++ b/docs/config-notes.txt @@ -602,6 +602,10 @@ generally forgoes saving of PID files, so `upsd -c ` would not work. If your workflow requires to manage these daemons beside the OS provided framework, you can customize it to start `upsd -FF` and save the PID file. +NUT releases after 2.8.0 define aliases for these units, so if your Linux +distribution uses NUT-provided unit definitions, `systemctl reload upsd` +may also work. + NOTE: If you want to make reloading work later, see the entry in the link:FAQ.html[FAQ] about starting `upsd` as a different user. diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index fd3843c5ac..1debe7f9a5 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -88,9 +88,18 @@ RELOADING upsd can reload its configuration files without shutting down the process if you send it a SIGHUP or start it again with `-c reload`. This only works if the background process is able to read those files, and if the daemon did -save a PID file when it started (e.g. service instances wrapped by systemd -or SMF might not save them by default -- use respective `reload`/`refresh` -framework actions instead then). +save a PID file when it started. + +[NOTE] +====== +Service instances wrapped by systemd or SMF might not save them by default -- +use respective `reload`/`refresh` framework actions instead then), e.g. +`systemctl reload nut-server` + +NUT releases after 2.8.0 define aliases for these units, so if your Linux +distribution uses NUT-provided unit definitions, `systemctl reload upsd` +may also work. +====== If you think that upsd can't reload, check your syslog for error messages. If it's complaining about not being able to read the files, then you need From 1e2daeb78fe34e37e869b350e14aff92cbffb684 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 20:35:21 +0100 Subject: [PATCH 0295/1232] clients/upsmon.c: cosmetic fixes --- clients/upsmon.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index f0767a5aa1..e58718735e 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1927,13 +1927,12 @@ static void pollups(utype_t *ups) /* try to make some of these a little friendlier */ switch (upscli_upserror(&ups->conn)) { - case UPSCLI_ERR_UNKNOWNUPS: upslogx(LOG_ERR, "Poll UPS [%s] failed - [%s] " - "does not exist on server %s", - ups->sys, ups->upsname, ups->hostname); - + "does not exist on server %s", + ups->sys, ups->upsname, ups->hostname); break; + default: upslogx(LOG_ERR, "Poll UPS [%s] failed - %s", ups->sys, upscli_strerror(&ups->conn)); From db7fab4741e393bbb1065e33fa09d593090be701 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 21:27:37 +0100 Subject: [PATCH 0296/1232] upsmon: Introduce POLLFAIL_LOG_THROTTLE_MAX [#506] --- NEWS | 3 +- clients/upsclient.h | 2 + clients/upsmon.c | 137 ++++++++++++++++++++++++++++++++++--- clients/upsmon.h | 6 ++ conf/upsmon.conf.sample.in | 14 ++++ docs/man/upsmon.conf.txt | 12 ++++ docs/man/upsmon.txt | 10 +++ docs/nut.dict | 4 +- 8 files changed, 178 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index a640603a71..161b8bcf57 100644 --- a/NEWS +++ b/NEWS @@ -220,7 +220,8 @@ https://github.com/networkupstools/nut/milestone/8 - Several fixes for `upsmon` behavior [#1761, #1680...], including new ability to configure default POWERDOWNFLAG location -- packagers are encouraged to pick optimal location for their distributions (which - remains mounted at least read-only late in shutdown) [#529] + remains mounted at least read-only late in shutdown) and a new optional + POLLFAIL_LOG_THROTTLE_MAX setting [#529, #506] - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, diff --git a/clients/upsclient.h b/clients/upsclient.h index e346d8f519..c79be96cfd 100644 --- a/clients/upsclient.h +++ b/clients/upsclient.h @@ -134,6 +134,8 @@ int upscli_ssl(UPSCONN_t *ups); /* upsclient error list */ +#define UPSCLI_ERR_NONE -1 /* No known error (internally used in tools like upsmon, not set by upsclient.c) */ + #define UPSCLI_ERR_UNKNOWN 0 /* Unknown error */ #define UPSCLI_ERR_VARNOTSUPP 1 /* Variable not supported by UPS */ #define UPSCLI_ERR_NOSUCHHOST 2 /* No such host */ diff --git a/clients/upsmon.c b/clients/upsmon.c index e58718735e..a38a55fe4a 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -55,6 +55,18 @@ static int deadtime = 15; /* default polling interval = 5 sec */ static unsigned int pollfreq = 5, pollfreqalert = 5; + /* If pollfail_log_throttle_max > 0, error messages for same + * state of an UPS (e.g. "Data stale" or "Driver not connected") + * will only be repeated every so many POLLFREQ loops. + * If pollfail_log_throttle_max == 0, such error messages will + * only be reported once when that situation starts, and ends. + * By default it is logged every pollfreq (which can abuse syslog + * and its storage). + * To support this, each utype_t (UPS) structure tracks individual + * pollfail_log_throttle_count and pollfail_log_throttle_state + */ +static int pollfail_log_throttle_max = -1; + /* secondary hosts are given 15 sec by default to logout from upsd */ static int hostsync = 15; @@ -1050,6 +1062,11 @@ static void drop_connection(utype_t *ups) ups->commstate = 0; ups->linestate = 0; + + /* forget poll-failure logging throttling */ + ups->pollfail_log_throttle_count = -1; + ups->pollfail_log_throttle_state = UPSCLI_ERR_NONE; + clearflag(&ups->status, ST_LOGIN); clearflag(&ups->status, ST_CLICONNECTED); @@ -1241,6 +1258,10 @@ static void addups(int reloading, const char *sys, const char *pvs, tmp->commstate = -1; tmp->linestate = -1; + /* forget poll-failure logging throttling */ + tmp->pollfail_log_throttle_count = -1; + tmp->pollfail_log_throttle_state = UPSCLI_ERR_NONE; + tmp->lastpoll = 0; tmp->lastnoncrit = 0; tmp->lastrbwarn = 0; @@ -1432,6 +1453,17 @@ static int parse_conf_arg(size_t numargs, char **arg) return 1; } + /* POLLFAIL_LOG_THROTTLE_MAX */ + if (!strcmp(arg[0], "POLLFAIL_LOG_THROTTLE_MAX")) { + int ipollfail_log_throttle_max = atoi(arg[1]); + if (ipollfail_log_throttle_max < 0 || ipollfail_log_throttle_max == INT_MAX) { + upsdebugx(0, "Ignoring invalid POLLFAIL_LOG_THROTTLE_MAX value: %d", ipollfail_log_throttle_max); + } else { + pollfail_log_throttle_max = ipollfail_log_throttle_max; + } + return 1; + } + /* HOSTSYNC */ if (!strcmp(arg[0], "HOSTSYNC")) { hostsync = atoi(arg[1]); @@ -1640,6 +1672,12 @@ static void loadconfig(void) nut_debug_level_args); nut_debug_level = nut_debug_level_args; } + + if (pollfail_log_throttle_max >= 0) { + upslogx(LOG_INFO, + "Applying pollfail_log_throttle_max=%d from upsmon.conf", + pollfail_log_throttle_max); + } } pconf_finish(&ctx); @@ -1902,11 +1940,15 @@ static void parse_status(utype_t *ups, char *status) static void pollups(utype_t *ups) { char status[SMALLBUF]; + int pollfail_log = 0; /* if we throttle, only upsdebugx() but not upslogx() the failures */ + int upserror; /* try a reconnect here */ - if (!flag_isset(ups->status, ST_CLICONNECTED)) - if (try_connect(ups) != 1) + if (!flag_isset(ups->status, ST_CLICONNECTED)) { + if (try_connect(ups) != 1) { return; + } + } if (upscli_ssl(&ups->conn) == 1) upsdebugx(2, "%s: %s [SSL]", __func__, ups->sys); @@ -1917,6 +1959,27 @@ static void pollups(utype_t *ups) if (get_var(ups, "status", status, sizeof(status)) == 0) { clear_alarm(); + + /* reset pollfail log throttling */ +#if 0 + /* Note: last error is never cleared, so we reset it below */ + upserror = upscli_upserror(&ups->conn); + upsdebugx(3, "%s: Poll UPS [%s] after getvar(status) okay: upserror=%d: %s", + __func__, ups->sys, upserror, upscli_strerror(&ups->conn)); +#endif + upserror = UPSCLI_ERR_NONE; + if (pollfail_log_throttle_max >= 0 + && ups->pollfail_log_throttle_state != upserror + ) { + /* Notify throttled log that we are okay now */ + upslogx(LOG_ERR, "Poll UPS [%s] recovered from " + "failure state code %d - now %d", + ups->sys, ups->pollfail_log_throttle_state, + upserror); + } + ups->pollfail_log_throttle_state = upserror; + ups->pollfail_log_throttle_count = -1; + parse_status(ups, status); return; } @@ -1925,17 +1988,75 @@ static void pollups(utype_t *ups) clear_alarm(); /* try to make some of these a little friendlier */ + upserror = upscli_upserror(&ups->conn); + upsdebugx(3, "%s: Poll UPS [%s] after getvar(status) failed: upserror=%d", + __func__, ups->sys, upserror); + if (pollfail_log_throttle_max < 0) { + /* Log properly on each loop */ + pollfail_log = 1; + } else { + if (ups->pollfail_log_throttle_state == upserror) { + /* known issue, no syslog spam now... maybe */ + if (pollfail_log_throttle_max == 0) { + /* Only log once for start or end of the same + * failure state */ + pollfail_log = 0; + } else { + /* Only log once for start, every MAX iterations, + * and end of the same failure state */ + if (ups->pollfail_log_throttle_count++ >= pollfail_log_throttle_max) { + /* ping... */ + pollfail_log = 1; + ups->pollfail_log_throttle_count = 0; + } else { + pollfail_log = 0; + } + } + } else { + /* new error => reset pollfail log throttling and log it + * now (numeric states here, string for new state below) */ + if (pollfail_log_throttle_max == 0) { + upslogx(LOG_ERR, "Poll UPS [%s] failure state code " + "changed from %d to %d; " + "report below will not be repeated to syslog:", + ups->sys, ups->pollfail_log_throttle_state, + upserror); + } else { + upslogx(LOG_ERR, "Poll UPS [%s] failure state code " + "changed from %d to %d; " + "report below will only be repeated to syslog " + "every %d polling loop cycles:", + ups->sys, ups->pollfail_log_throttle_state, + upserror, pollfail_log_throttle_max); + } - switch (upscli_upserror(&ups->conn)) { + ups->pollfail_log_throttle_state = upserror; + ups->pollfail_log_throttle_count = 0; + pollfail_log = 1; + } + } + + switch (upserror) { case UPSCLI_ERR_UNKNOWNUPS: - upslogx(LOG_ERR, "Poll UPS [%s] failed - [%s] " - "does not exist on server %s", - ups->sys, ups->upsname, ups->hostname); + if (pollfail_log) { + upslogx(LOG_ERR, "Poll UPS [%s] failed - [%s] " + "does not exist on server %s", + ups->sys, ups->upsname, ups->hostname); + } else { + upsdebugx(1, "Poll UPS [%s] failed - [%s] " + "does not exist on server %s", + ups->sys, ups->upsname, ups->hostname); + } break; default: - upslogx(LOG_ERR, "Poll UPS [%s] failed - %s", - ups->sys, upscli_strerror(&ups->conn)); + if (pollfail_log) { + upslogx(LOG_ERR, "Poll UPS [%s] failed - %s", + ups->sys, upscli_strerror(&ups->conn)); + } else { + upsdebugx(1, "Poll UPS [%s] failed - [%s]", + ups->sys, upscli_strerror(&ups->conn)); + } break; } diff --git a/clients/upsmon.h b/clients/upsmon.h index f386f3f8e1..a7946addae 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -61,6 +61,12 @@ typedef struct { int commstate; /* these start at -1, and only */ int linestate; /* fire on a 0->1 transition */ + /* see detailed comment for pollfail_log_throttle_max in upsmon.c + * about handling of poll failure log throttling (syslog storage I/O) + */ + int pollfail_log_throttle_state; /* Last (error) state which we throttle */ + int pollfail_log_throttle_count; /* How many pollfreq loops this UPS was in this state since last logged report? */ + time_t lastpoll; /* time of last successful poll */ time_t lastnoncrit; /* time of last non-crit poll */ time_t lastrbwarn; /* time of last REPLBATT warning*/ diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 9986cc44b0..4f4ca1e56a 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -348,6 +348,20 @@ RBWARNTIME 43200 NOCOMMWARNTIME 300 +# -------------------------------------------------------------------------- +# POLLFAIL_LOG_THROTTLE_MAX - device poll failure logging throttle +# +# upsmon normally reports polling failures for each device that are in place +# for each POLLFREQ loop (e.g. "Data stale" or "Driver not connected") to +# system log as configured. If your devices are expected to be AWOL for an +# extended timeframe, you can use this throttle to reduce the stress on +# syslog traffic and storage, by posting these messages only once in every +# several loop cycles, and when the error condition has changed or cleared. +# A negative value means standard behavior, and a zero value means to never +# repeat the message (log only on start and end/change of the failure state). +# +#POLLFAIL_LOG_THROTTLE_MAX 100 + # -------------------------------------------------------------------------- # FINALDELAY - last sleep interval before shutting down the system # diff --git a/docs/man/upsmon.conf.txt b/docs/man/upsmon.conf.txt index 4b38bc12f4..1d4f6c3df4 100644 --- a/docs/man/upsmon.conf.txt +++ b/docs/man/upsmon.conf.txt @@ -163,6 +163,18 @@ reach any of the UPS entries in this configuration file. It keeps warning you until the situation is fixed. By default this is 300 seconds. +*POLLFAIL_LOG_THROTTLE_MAX* 'count':: + +upsmon normally reports polling failures for each device that are in place +for each POLLFREQ loop (e.g. "Data stale" or "Driver not connected") to +system log as configured. If your devices are expected to be AWOL for an +extended timeframe, you can use this throttle to reduce the stress on +syslog traffic and storage, by posting these messages only once in every +several loop cycles, and when the error condition has changed or cleared. + +A negative value means standard behavior, and a zero value means to never +repeat the message (log only on start and end/change of the failure state). + *NOTIFYCMD* 'command':: upsmon calls this to send messages when things happen. diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index 313cf2983c..c983deaea5 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -441,6 +441,16 @@ upsmon will alert you to a UPS that can't be contacted for monitoring with a "NOCOMM" notifier by default every 300 seconds. This can be changed with the NOCOMMWARNTIME setting. +Also upsmon normally reports polling failures for each device that are in place +for each POLLFREQ loop (e.g. "Data stale" or "Driver not connected") to +system log as configured. If your devices are expected to be AWOL for an +extended timeframe, you can use POLLFAIL_LOG_THROTTLE_MAX to reduce the +stress on syslog traffic and storage, by posting these messages only once +in every several loop cycles, and when the error condition has changed or +cleared. A negative value means standard behavior, and a zero value means +to never repeat the message (log only on start and end/change of the failure +state). + RELOADING NUANCES ----------------- diff --git a/docs/nut.dict b/docs/nut.dict index bd1fd31a52..0ff5c5790e 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3067 utf-8 +personal_ws-1.1 en 3069 utf-8 AAS ABI ACFAIL @@ -846,6 +846,7 @@ PIPEFN PLD PLL PLVn +POLLFAIL POLLFREQALERT POMode POSIX @@ -2818,6 +2819,7 @@ testuser textproc th timehead +timeframe timeline timername timestamp From ad70749f243527e774c3f03a08228430143396e9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Jan 2023 23:02:19 +0100 Subject: [PATCH 0297/1232] common/common.c: fix if/ifdef for configure-detected methods [#1590, #1739] --- common/common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/common.c b/common/common.c index 9a82a69402..88469790b3 100644 --- a/common/common.c +++ b/common/common.c @@ -673,7 +673,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) __func__, state); upsnotify_reported_disabled_systemd = 1; } else { -# if HAVE_SD_NOTIFY +# ifdef HAVE_SD_NOTIFY # if ! DEBUG_SYSTEMD_WATCHDOG if (state != NOTIFY_STATE_WATCHDOG || !upsnotify_reported_watchdog_systemd) @@ -759,7 +759,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (1) { /* scoping */ int postit = 0; -# if HAVE_SD_WATCHDOG_ENABLED +# ifdef HAVE_SD_WATCHDOG_ENABLED uint64_t to = 0; postit = sd_watchdog_enabled(0, &to); @@ -889,7 +889,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) * and post a watchdog message but systemd did not * yet prepare to handle us */ upsdebugx(6, "%s: wait for NOTIFY_STATE_READY_WITH_PID to be handled by systemd", __func__); -# if HAVE_SD_NOTIFY_BARRIER +# ifdef HAVE_SD_NOTIFY_BARRIER sd_notify_barrier(0, UINT64_MAX); # else usleep(3 * 1000000); @@ -910,7 +910,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) #endif /* WITH_LIBSYSTEMD */ if (ret < 0 -#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && HAVE_SD_NOTIFY +#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && (defined(HAVE_SD_NOTIFY) && HAVE_SD_NOTIFY) # if ! DEBUG_SYSTEMD_WATCHDOG && (!upsnotify_reported_watchdog_systemd || (state != NOTIFY_STATE_WATCHDOG)) # endif From b936c85d5551cf7b233c4829df5c99afc15dc5a7 Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Sun, 8 Jan 2023 11:32:27 -0500 Subject: [PATCH 0298/1232] upsd.conf.sample: Clarify LISTEN/firewall comments --- conf/upsd.conf.sample | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/conf/upsd.conf.sample b/conf/upsd.conf.sample index 3f87800fe3..8c8f95a634 100644 --- a/conf/upsd.conf.sample +++ b/conf/upsd.conf.sample @@ -58,20 +58,22 @@ # LISTEN myhostname 83493 # LISTEN myhostname.mydomain # -# This defaults to the localhost listening addresses and port 3493. -# In case of IP v4 or v6 disabled kernel, only the available one will be used. +# With no LISTEN statement, the default is localhost and port 3493. +# In case of IP v4 or v6 disabled kernel, only the available one will +# be used. # Note that it is not true for Windows platforms. You shouldn't use IPv6 in # your configuration files unless you have IPv6 installed. # -# You may specify each interface IP address or name that you want upsd to -# listen on for connections, optionally with a port number. +# One or more LISTEN statements give the IP address (or name that +# resolves to such an address) for upsd to listen on, optionally with +# a port number. # -# You may need this if you have multiple interfaces on your machine and -# you don't want upsd to listen to all interfaces (for instance on a -# firewall, you may not want to listen to the external interface). +# As an example, a machine with a LAN and a WAN interface that also +# functions as a router and firewall might be configured to listen +# only on the LAN interface. # # This will only be read at startup of upsd. If you make changes here, -# you'll need to restart upsd, reload will have no effect. +# you'll need to restart upsd, as reload will have no effect. # ======================================================================= # MAXCONN From e0a15cc6b9300fa860a61730f59ab99038d952ac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 11:01:05 +0100 Subject: [PATCH 0299/1232] drivers/libusb{0,1}.c: bump version for allow_duplicates [#1756] --- drivers/libusb0.c | 2 +- drivers/libusb1.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 8d8c9e1bf0..8872ca471b 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -37,7 +37,7 @@ #endif #define USB_DRIVER_NAME "USB communication driver (libusb 0.1)" -#define USB_DRIVER_VERSION "0.43" +#define USB_DRIVER_VERSION "0.44" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 8a096a2103..ca37a4c789 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define USB_DRIVER_NAME "USB communication driver (libusb 1.0)" -#define USB_DRIVER_VERSION "0.43" +#define USB_DRIVER_VERSION "0.44" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { From cc379777ed5e7cf31553102330ba7fe19396005a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 13:02:40 +0100 Subject: [PATCH 0300/1232] docs/configure.txt: hint for builds of git checkouts [#1750] --- docs/configure.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 822fca1990..cfb58c3032 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -3,6 +3,27 @@ Configure options ================= endif::website[] +[NOTE] +====== +When building NUT from Git sources rather than the distribution tarballs, +you would have to generate the `configure` script and some further needed +files by running `./autogen.sh`. This in turn may require additional tools +and other dependencies on your build environment (referenced just a bit +below). For common developer iterations, porting to new platforms, +or in-place testing, running the `./ci_build.sh` script can be a helpful +one-stop solution. ++ +The NUT linkdoc:packager-guide[Packager Guide], which presents the best +practices for installing and integrating NUT, is also a good reading. ++ +The link:config-prereqs.txt[Prerequisites for building NUT on different OSes] +document suggests prerequisite packages with tools and dependencies +available and needed to build and test as much as possible of NUT on +numerous platforms, written from perspective of CI testing (if you +are interested in getting updated drivers for a particular device, +you might select a sub-set of those suggestions). +====== + There are a few options reviewed below that can be given to `configure` script to tweak your compilations. See also `./configure --help` for a current and complete listing for the current version of the codebase. From 6ea13657fddb0084c164df2bf8567c7a00ff5eb1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 13:03:37 +0100 Subject: [PATCH 0301/1232] docs/configure.txt: whitespace fixes --- docs/configure.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/configure.txt b/docs/configure.txt index cfb58c3032..d2a1657808 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -284,9 +284,9 @@ library). Networking transport security ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --with-ssl (default: auto-detect) - --with-nss (default: auto-detect) - --with-openssl (default: auto-detect) + --with-ssl (default: auto-detect) + --with-nss (default: auto-detect) + --with-openssl (default: auto-detect) Enable SSL support, using either Mozilla NSS or OpenSSL. From 77f334d67b0372a4fe230fa53692bf36cb9c084f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 13:52:20 +0100 Subject: [PATCH 0302/1232] docs/configure.txt: document python, pynut and nut_monitor related options and autogen.sh fuss about it [#1787] --- docs/configure.txt | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index d2a1657808..1238f14334 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -238,6 +238,92 @@ Example valid formats of this flag: * `--with-doc=pdf,html-chunked` * `--with-doc=man=no,pdf=auto,html-single` +Python support +~~~~~~~~~~~~~~ + +NUT includes a client binding `PyNUT` module, as well as an optional GUI +application `NUT-Monitor` (not to be confused with `nut-monitor` service +name for `upsmon` as delivered by some OS distribution packages). Both +python 2.7 and several versions of python 3.x are supported and regularly +tested by NUT CI farm builds; other versions may work or not. + +Also some of the source configuration (including activity in `autogen.sh` +script and later in certain `Makefile`s during build) relies on presence +of `python` (and `perl`) interpreters. If they are not available, e.g. on +older operating systems, certain features are skipped -- but you may have +to `export` special environment variables to signal to `autogen.sh` that +this is an expected situation (it would suggest which, for your current +NUT version). + +Since this is an area which impacts both `configure` script generation by +the helper `autogen.sh` script and subsequently the choices made by the +`configure` script itself, settings can be made by exporting the `PYTHON` +environment variables which should evaluate to some way to call the correct +interpreter (e.g. `python2.7`, `/usr/bin/env python` or `/usr/bin/python3`). + +The `configure` script does support equivalent options, whose defaults +come from such environment variables (if specified and exported by caller). +Further use of the interpreter names and other paths during NUT build and +installation is managed by Makefile variable expansion, as prepared by +the `configure` script. + +As noted above, both python-2.x and python-3.x variants are supported. +For consistency, they can be defaulted for the `configure` script by +exporting `PYTHON2` and `PYTHON3` environment variables, respectively. +Otherwise, consult `m4/nut_check_python.m4` for detection methods used. +If both interpreter generations are present, and a particular un-versioned +`PYTHON` is not specified, then selected/detected `PYTHON3` is chosen as +the ultimate `PYTHON` value. + +For majority of uses in the build procedure and products, the generation +of Python does not matter and the un-versioned `PYTHON` value is substituted +into files as the script shebang, used to find the `site-packages` location, +etc. + +One exception is generation of NUT-Monitor GUI application which has been +separated for `NUT-Monitor-py2gtk2` and `NUT-Monitor-py3qt5` due to further +backend platform technical differences -- these build products specifically +use `PYTHON2` and `PYTHON3` substitutions. They may be co-installed on the +same system. A dispatcher shell script `NUT-Monitor` is used to launch the +preferred (newest) or the only existing implementation. + +The settings below may be of particular interest to non-distribution +packaging efforts with their own dedicated directory trees: + + --with-python=SHEBANG_PATH + +Specify a definitive version you want used for majority of the Python +code (except version-dependent scripts, see above). + +The `SHEBANG_PATH` should be a full program pathname, optionally with +one argument, e.g. `/usr/bin/python-3.9` or `/usr/bin/env python2`. + +Defaults (in order): +* `PYTHON` environment variable, +* `python` program if present in `PATH`, +* `python3` program if present in `PATH`, +* `python2` program if present in `PATH`, +* or the newest of `PYTHON3` or `PYTHON2` values. + + --with-python2=SHEBANG_PATH + --with-python3=SHEBANG_PATH + +For version-dependent scripts (see above) or to default the newest Python +version if not specified by `--with-python` option or `PYTHON` envvar, +you can provide the preferred version and implementation of Python 2 or 3 +respectively. + + --with-nut_monitor + +Install the NUT-Monitor GUI application (depending on Python 2 or 3 version +availability), and optional `desktop-file-install` integration). + + --with-pynut + +Install the PyNUT module files for general consumption into "site-packages" +location of the currently chosen Python interpreter(s): yes, no, auto. +or dedicated as the required dependency of NUT-Monitor application (app). + Development files ~~~~~~~~~~~~~~~~~ From 799c70086f295d0ab62cad5754e33a12adc5f598 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 14:13:13 +0100 Subject: [PATCH 0303/1232] docs/configure.txt: current configure script does not use "PYTHON{,2,3}" envvars [#1787] --- docs/configure.txt | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/configure.txt b/docs/configure.txt index 1238f14334..235977ce48 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -255,25 +255,25 @@ to `export` special environment variables to signal to `autogen.sh` that this is an expected situation (it would suggest which, for your current NUT version). -Since this is an area which impacts both `configure` script generation by -the helper `autogen.sh` script and subsequently the choices made by the -`configure` script itself, settings can be made by exporting the `PYTHON` -environment variables which should evaluate to some way to call the correct -interpreter (e.g. `python2.7`, `/usr/bin/env python` or `/usr/bin/python3`). +NOTE: For CI builds (or similar reproducible developer activity) performed +with `ci_build.sh` -- since this is an area which impacts both `configure` +script generation by the helper `autogen.sh` script and subsequently the +choices made by the `configure` script itself, settings can be made by +exporting the `PYTHON` environment variable which should evaluate to some +way to call the correct interpreter (e.g. `python2.7`, `/usr/bin/env python` +or `/usr/bin/python3`). The `configure` script does support equivalent options, whose defaults -come from such environment variables (if specified and exported by caller). -Further use of the interpreter names and other paths during NUT build and -installation is managed by Makefile variable expansion, as prepared by -the `configure` script. +come from detection of certain program names by current `PATH` setting. +Further use of these interpreter names and other paths during NUT build +and installation is managed by Makefile variable expansion, as prepared +by the `configure` script. As noted above, both python-2.x and python-3.x variants are supported. -For consistency, they can be defaulted for the `configure` script by -exporting `PYTHON2` and `PYTHON3` environment variables, respectively. -Otherwise, consult `m4/nut_check_python.m4` for detection methods used. +You can consult the `m4/nut_check_python.m4` file for detection methods used. If both interpreter generations are present, and a particular un-versioned -`PYTHON` is not specified, then selected/detected `PYTHON3` is chosen as -the ultimate `PYTHON` value. +`PYTHON` is not specified or detected, then selected/detected `PYTHON3` is +chosen as the ultimate `PYTHON` value. For majority of uses in the build procedure and products, the generation of Python does not matter and the un-versioned `PYTHON` value is substituted @@ -299,17 +299,14 @@ The `SHEBANG_PATH` should be a full program pathname, optionally with one argument, e.g. `/usr/bin/python-3.9` or `/usr/bin/env python2`. Defaults (in order): -* `PYTHON` environment variable, -* `python` program if present in `PATH`, -* `python3` program if present in `PATH`, -* `python2` program if present in `PATH`, -* or the newest of `PYTHON3` or `PYTHON2` values. +* `python`, `python3` or `python2` program if present in `PATH` by such name, +* or the newest of `PYTHON3` or `PYTHON2` values (specified or detected below). --with-python2=SHEBANG_PATH --with-python3=SHEBANG_PATH For version-dependent scripts (see above) or to default the newest Python -version if not specified by `--with-python` option or `PYTHON` envvar, +version if not specified by `--with-python` option or detected otherwise, you can provide the preferred version and implementation of Python 2 or 3 respectively. From e1f2affe41bde6327dcfdefb4700819646875872 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 14:08:55 +0100 Subject: [PATCH 0304/1232] configure.ac, m4/nut_check_python.m4: refactor with NUT_CHECK_PYTHON_DEFAULT [#1518] --- configure.ac | 17 +---------------- m4/nut_check_python.m4 | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 0bd0f1af6d..aaecde96d8 100644 --- a/configure.ac +++ b/configure.ac @@ -774,22 +774,7 @@ AS_IF([test x"${ac_cv_func_inet_ntop}" = xyes], dnl ---------------------------------------------------------------------- dnl Check for python binary program names per language version dnl to embed into scripts and Make rules -NUT_CHECK_PYTHON -NUT_CHECK_PYTHON2 -NUT_CHECK_PYTHON3 -AS_IF([test x"$PYTHON2" = xno], [PYTHON2=""]) -AS_IF([test x"$PYTHON3" = xno], [PYTHON3=""]) -AS_IF([test x"$PYTHON" = xno], [PYTHON=""]) -AS_IF([test x"$PYTHON" = x], [ - AC_MSG_CHECKING([which python version to use by default]) - dnl Last hit wins (py3) - AS_IF([test x"$PYTHON2" != x], [PYTHON="$PYTHON2"]) - AS_IF([test x"$PYTHON3" != x], [PYTHON="$PYTHON3"]) - AS_IF([test x"$PYTHON" = x], - [AC_MSG_RESULT([none])], - [AC_MSG_RESULT([$PYTHON])] - ) - ]) +NUT_CHECK_PYTHON_DEFAULT dnl ---------------------------------------------------------------------- dnl check for --with-drivers=all (or --with-drivers=name[,name...]) flag diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index f9680a1fa3..b2a91d0729 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -1,6 +1,31 @@ dnl Check for python binary program names per language version dnl to embed into scripts and Make rules +AC_DEFUN([NUT_CHECK_PYTHON_DEFAULT], +[ + dnl Check for all present variants and pick the default PYTHON + AC_REQUIRE([NUT_CHECK_PYTHON]) + AC_REQUIRE([NUT_CHECK_PYTHON2]) + AC_REQUIRE([NUT_CHECK_PYTHON3]) + + AS_IF([test x"$PYTHON2" = xno], [PYTHON2=""]) + AS_IF([test x"$PYTHON3" = xno], [PYTHON3=""]) + AS_IF([test x"$PYTHON" = xno], [PYTHON=""]) + AS_IF([test x"$PYTHON" = x], [ + AC_MSG_CHECKING([which python version to use by default]) + dnl Last hit wins (py3) + AS_IF([test x"$PYTHON2" != x], [PYTHON="$PYTHON2"]) + AS_IF([test x"$PYTHON3" != x], [PYTHON="$PYTHON3"]) + AS_IF([test x"$PYTHON" = x], + [AC_MSG_RESULT([none])], + [AC_MSG_RESULT([$PYTHON])] + ) + ]) +]) + +dnl Note: this checks for default/un-versioned python version +dnl as the --with-python=SHEBANG_PATH setting into the PYTHON +dnl variable; it may be further tweaked by NUT_CHECK_PYTHON_DEFAULT AC_DEFUN([NUT_CHECK_PYTHON], [ AS_IF([test -z "${nut_with_python}"], [ From 13367e5cd55b3858a54b8aa7e6af6c6bd88cffb7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 15:26:09 +0100 Subject: [PATCH 0305/1232] m4/nut_check_python.m4: actually fail if a Python version was required but not found [#1787] --- m4/nut_check_python.m4 | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index b2a91d0729..1a1f0ed4c0 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -21,6 +21,18 @@ AC_DEFUN([NUT_CHECK_PYTHON_DEFAULT], [AC_MSG_RESULT([$PYTHON])] ) ]) + + AS_IF([test -z "${PYTHON3}" && test x"${nut_with_python3}" = xyes], [ + AC_MSG_ERROR([A python3 interpreter was required but not found or validated]) + ]) + + AS_IF([test -z "${PYTHON2}" && test x"${nut_with_python2}" = xyes], [ + AC_MSG_ERROR([A python2 interpreter was required but not found or validated]) + ]) + + AS_IF([test -z "${PYTHON}" && test x"${nut_with_python}" = xyes], [ + AC_MSG_ERROR([A python interpreter was required but not found or validated]) + ]) ]) dnl Note: this checks for default/un-versioned python version @@ -69,6 +81,13 @@ AC_DEFUN([NUT_CHECK_PYTHON], PYTHON=no]) ]) + dnl Unfulfilled "yes" is re-tested in NUT_CHECK_PYTHON_DEFAULT + AS_IF([test -z "${PYTHON}" || test "${PYTHON}" = "no"], [ + AS_CASE([${nut_with_python}], + [auto|yes|no|""], [], + [AC_MSG_ERROR([A python interpreter was required but not found or validated: ${nut_with_python}])]) + ]) + AC_MSG_CHECKING([python interpeter to call]) AC_MSG_RESULT([${PYTHON}${PYTHON_VERSION_REPORT}]) AC_SUBST([PYTHON], [${PYTHON}]) @@ -133,6 +152,13 @@ AC_DEFUN([NUT_CHECK_PYTHON2], PYTHON2=no]) ]) + dnl Unfulfilled "yes" is re-tested in NUT_CHECK_PYTHON_DEFAULT + AS_IF([test -z "${PYTHON2}" || test "${PYTHON2}" = "no"], [ + AS_CASE([${nut_with_python2}], + [auto|yes|no|""], [], + [AC_MSG_ERROR([A python2 interpreter was required but not found or validated: ${nut_with_python2}])]) + ]) + AC_MSG_CHECKING([python2 interpeter to call]) AC_MSG_RESULT([${PYTHON2}${PYTHON2_VERSION_REPORT}]) AC_SUBST([PYTHON2], [${PYTHON2}]) @@ -197,6 +223,13 @@ AC_DEFUN([NUT_CHECK_PYTHON3], PYTHON3=no]) ]) + dnl Unfulfilled "yes" is re-tested in NUT_CHECK_PYTHON_DEFAULT + AS_IF([test -z "${PYTHON3}" || test "${PYTHON3}" = "no"], [ + AS_CASE([${nut_with_python3}], + [auto|yes|no|""], [], + [AC_MSG_ERROR([A python3 interpreter was required but not found or validated: ${nut_with_python3}])]) + ]) + AC_MSG_CHECKING([python3 interpeter to call]) AC_MSG_RESULT([${PYTHON3}${PYTHON3_VERSION_REPORT}]) AC_SUBST([PYTHON3], [${PYTHON3}]) From 79b02fbc5634f8546fb6c6e8e94e7e181531b942 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 15:39:19 +0100 Subject: [PATCH 0306/1232] docs/configure.txt: clarify that autogen.sh and configure may default to different PYTHON versions [#1787] --- docs/configure.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 235977ce48..f55a01dcae 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -269,6 +269,9 @@ Further use of these interpreter names and other paths during NUT build and installation is managed by Makefile variable expansion, as prepared by the `configure` script. +Also note that it is not required to use the same `PYTHON` implementation +for `autogen.sh` to do its job, and for the `configure` script option. + As noted above, both python-2.x and python-3.x variants are supported. You can consult the `m4/nut_check_python.m4` file for detection methods used. If both interpreter generations are present, and a particular un-versioned From 0e2beedce1444f0af1e91f752c0e1be7589184c2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 15:50:21 +0100 Subject: [PATCH 0307/1232] m4/nut_check_python.m4: if --with-python2/3 are not specified, use exact path from --with-python (if available) to match its site-packages [#1787] --- m4/nut_check_python.m4 | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 1a1f0ed4c0..604d9b185d 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -126,8 +126,20 @@ AC_DEFUN([NUT_CHECK_PYTHON2], dnl if provided by the caller: AS_CASE([${PYTHON2}], [_python2_runtime], [ - PYTHON2="/usr/bin/env python2" - AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (scripts will fail if that is not in PATH at run time)])], + dnl Cross check --with-python results: + AS_CASE(["${PYTHON_VERSION_REPORT}"], + [*major=2,*], [ + AS_CASE([${PYTHON}], + [/usr/bin/env*], [], + [/*py*2*], [PYTHON2="${PYTHON}"]) + ]) + AS_IF([test x"${PYTHON2}" = x_python2_runtime], [ + PYTHON2="/usr/bin/env python2" + AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (scripts will fail if that is not in PATH at run time)]) + ],[ + AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (specified or detected as --with-python setting)]) + ]) + ], [no], [], [/*" "*" "*], [ AC_MSG_WARN([A python2 program name is not a single token (was specified with more than one argument?), so shebangs can be not reliable]) @@ -197,8 +209,20 @@ AC_DEFUN([NUT_CHECK_PYTHON3], dnl if provided by the caller: AS_CASE([${PYTHON3}], [_python3_runtime], [ - PYTHON3="/usr/bin/env python3" - AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (scripts will fail if that is not in PATH at run time)])], + dnl Cross check --with-python results: + AS_CASE(["${PYTHON_VERSION_REPORT}"], + [*major=3,*], [ + AS_CASE([${PYTHON}], + [/usr/bin/env*], [], + [/*py*3*], [PYTHON3="${PYTHON}"]) + ]) + AS_IF([test x"${PYTHON3}" = x_python3_runtime], [ + PYTHON3="/usr/bin/env python3" + AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (scripts will fail if that is not in PATH at run time)]) + ],[ + AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (specified or detected as --with-python setting)]) + ]) + ], [no], [], [/*" "*" "*], [ AC_MSG_WARN([A python3 program name is not a single token (was specified with more than one argument?), so shebangs can be not reliable]) From c2914159da20f18a64e71593557d301a18f30f5d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 13:27:31 +0100 Subject: [PATCH 0308/1232] powercom driver should try harder to refresh data from device [#356] --- NEWS | 2 ++ drivers/powercom.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 359e25c997..20e74e43ee 100644 --- a/NEWS +++ b/NEWS @@ -91,6 +91,8 @@ https://github.com/networkupstools/nut/milestone/8 to `battery.mfr.date` (not `battery.date` which is the maintenance replacement date) [#1644] + - powercom driver should now try harder to refresh data from device [#356] + - NUT for Windows: * Ability to build NUT for Windows, last tackled with a branch based on NUT v2.6.5 a decade ago, has been revived with the 2.8.x era codebase [#5]. diff --git a/drivers/powercom.c b/drivers/powercom.c index be647dbd4a..c3a45a1463 100644 --- a/drivers/powercom.c +++ b/drivers/powercom.c @@ -86,7 +86,7 @@ #include "math.h" #define DRIVER_NAME "PowerCom protocol UPS driver" -#define DRIVER_VERSION "0.19" +#define DRIVER_VERSION "0.20" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -770,8 +770,12 @@ void upsdrv_updateinfo(void) { char val[32]; - if (!ups_getinfo()){ - return; + if (!ups_getinfo()) { + /* https://github.com/networkupstools/nut/issues/356 */ + upsdebugx(1, "%s: failed to ups_getinfo() once, retrying for slower devices", __func__); + if (!ups_getinfo()) { + return; + } } /* input.frequency */ From 768d820c2e1e23c716ae44c0e7638fabbcf6239e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 10:59:20 +0100 Subject: [PATCH 0309/1232] nut-scanner: report same USB matching values as seeked by libusb{0,1}.c [#1790] --- NEWS | 4 ++ drivers/libusb0.c | 3 ++ drivers/libusb1.c | 3 ++ tools/nut-scanner/scan_usb.c | 81 ++++++++++++++++++++++++++++++++---- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 359e25c997..d0e425ba2e 100644 --- a/NEWS +++ b/NEWS @@ -146,6 +146,10 @@ https://github.com/networkupstools/nut/milestone/8 may help monitor several related no-name devices (although without knowing reliably which one is which... better than nothing) [#1756] + - The `nut-scanner` program should now suggest same configuration fields as + those used by common USB matching options in (most of the) drivers, e.g. + adding "device" to the generated configuration section [#1790] + - Stuck drivers that do not react to `SIGTERM` quickly are now retried with `SIGKILL` [#1424] diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 8872ca471b..5b3e87e6ab 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -289,6 +289,9 @@ static int libusb_open(usb_dev_handle **udevp, free(curDevice->Device); memset(curDevice, '\0', sizeof(*curDevice)); + /* Keep the list of items in sync with those matched by + * drivers/libusb1.c and tools/nut-scanner/scan_usb.c: + */ curDevice->VendorID = dev->descriptor.idVendor; curDevice->ProductID = dev->descriptor.idProduct; curDevice->Bus = xstrdup(bus->dirname); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index ca37a4c789..84aa4f23d9 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -239,6 +239,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Device); memset(curDevice, '\0', sizeof(*curDevice)); + /* Keep the list of items in sync with those matched by + * drivers/libusb0.c and tools/nut-scanner/scan_usb.c: + */ bus = libusb_get_bus_number(device); curDevice->Bus = (char *)malloc(4); if (curDevice->Bus == NULL) { diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 27f62036e8..93b0803922 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -53,6 +53,7 @@ static int (*nut_usb_get_string_simple)(libusb_device_handle *dev, int index, static ssize_t (*nut_usb_get_device_list)(libusb_context *ctx, libusb_device ***list); static void (*nut_usb_free_device_list)(libusb_device **list, int unref_devices); static uint8_t (*nut_usb_get_bus_number)(libusb_device *dev); + static uint8_t (*nut_usb_get_port_number)(libusb_device *dev); static int (*nut_usb_get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc); #else /* => WITH_LIBUSB_0_1 */ @@ -146,6 +147,16 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + /* Note: per https://nxmnpg.lemoda.net/3/libusb_get_device_address there + * was a libusb_get_port_path() equivalent with different arguments, but + * not for too long (libusb-1.0.12...1.0.16) and now it is deprecated. + */ + *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, + "libusb_get_port_number"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } + *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { @@ -222,14 +233,31 @@ nutscan_device_t * nutscan_scan_usb() { int ret; char string[256]; + /* Items below are learned by libusbN version-specific API code + * Keep in sync with items matched by drivers/libusb{0,1}.c + * (nut)libusb_open methods, and fields of USBDevice_t struct + * (drivers/usb-common.h). + */ char *driver_name = NULL; char *serialnumber = NULL; char *device_name = NULL; char *vendor_name = NULL; uint8_t iManufacturer = 0, iProduct = 0, iSerialNumber = 0; - uint16_t VendorID; - uint16_t ProductID; - char *busname; + uint16_t VendorID = 0; + uint16_t ProductID = 0; + char *busname = NULL; + /* device_port physical meaning: connection port on that bus; + * different consumers plugged into same socket should have + * the same port value. However in practice such functionality + * depends on platform and HW involved. + * In libusb1 API: libusb_get_port_numbers() earlier known + * as libusb_get_port_path() for physical port number on the bus, see + * https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html#ga14879a0ea7daccdcddb68852d86c00c4 + * In libusb0 API: "device filename" + */ + char *device_port = NULL; + /* bcdDevice: aka "Device release number" - note we currently do not match by it */ + uint16_t bcdDevice = 0; #if WITH_LIBUSB_1_0 libusb_device *dev; libusb_device **devlist; @@ -283,6 +311,7 @@ nutscan_device_t * nutscan_scan_usb() iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; bus = (*nut_usb_get_bus_number)(dev); + busname = (char *)malloc(4); if (busname == NULL) { (*nut_usb_free_device_list)(devlist, 1); @@ -290,6 +319,22 @@ nutscan_device_t * nutscan_scan_usb() fatal_with_errno(EXIT_FAILURE, "Out of memory"); } snprintf(busname, 4, "%03d", bus); + + device_port = (char *)malloc(4); + if (device_port == NULL) { + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } else { + uint8_t port = (*nut_usb_get_port_number)(dev); + if (port > 0) { + snprintf(device_port, 4, "%03d", port); + } else { + snprintf(device_port, 4, ".*"); + } + } + + bcdDevice = dev_desc.bcdDevice; #else /* => WITH_LIBUSB_0_1 */ # ifndef WIN32 for (bus = (*nut_usb_busses); bus; bus = bus->next) { @@ -305,6 +350,8 @@ nutscan_device_t * nutscan_scan_usb() iProduct = dev->descriptor.iProduct; iSerialNumber = dev->descriptor.iSerialNumber; busname = bus->dirname; + device_port = dev->filename; + bcdDevice = dev->descriptor.bcdDevice; #endif if ((driver_name = is_usb_device_supported(usb_device_table, @@ -314,9 +361,9 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 ret = (*nut_usb_open)(dev, &udev); if (!udev || ret != LIBUSB_SUCCESS) { - fprintf(stderr,"Failed to open device " - "bus '%s', skipping: %s\n", - busname, + fprintf(stderr, "Failed to open device " + "bus '%s' device/port '%s', skipping: %s\n", + busname, device_port, (*nut_usb_strerror)(ret)); /* Note: closing is not applicable @@ -325,7 +372,8 @@ nutscan_device_t * nutscan_scan_usb() * when e.g. permissions problem) */ - free (busname); + free(busname); + free(device_port); continue; } @@ -334,8 +382,8 @@ nutscan_device_t * nutscan_scan_usb() if (!udev) { /* TOTHINK: any errno or similar to test? */ fprintf(stderr, "Failed to open device " - "bus '%s',skipping: %s\n", - busname, + "bus '%s' device/port '%s', skipping: %s\n", + busname, device_port, (*nut_usb_strerror)()); continue; } @@ -351,6 +399,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_close)(udev); #if WITH_LIBUSB_1_0 free(busname); + free(device_port); (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -370,6 +419,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_close)(udev); #if WITH_LIBUSB_1_0 free(busname); + free(device_port); (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -390,6 +440,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_close)(udev); #if WITH_LIBUSB_1_0 free(busname); + free(device_port); (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -409,6 +460,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_close)(udev); #if WITH_LIBUSB_1_0 free(busname); + free(device_port); (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -459,6 +511,16 @@ nutscan_device_t * nutscan_scan_usb() "bus", busname); + nutscan_add_option_to_device(nut_dev, + "device", + device_port); + + /* Not currently matched by drivers, hence commented for now: */ + sprintf(string, "%04X", bcdDevice); + nutscan_add_option_to_device(nut_dev, + "###NOTMATCHED-YET###bcdDevice", + string); + current_nut_dev = nutscan_add_device_to_device( current_nut_dev, nut_dev); @@ -472,6 +534,7 @@ nutscan_device_t * nutscan_scan_usb() } #else /* not WITH_LIBUSB_0_1 */ free(busname); + free(device_port); } (*nut_usb_free_device_list)(devlist, 1); From 8288889ca228ce6d340ec1f145c5a465be6afa30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 14:57:44 +0100 Subject: [PATCH 0310/1232] ci_build.sh: copy-paste typo fix for CANBUILD_NIT_TESTS handling --- ci_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index 145986d8e8..a556d14571 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -983,7 +983,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # would quickly regenerate Makefile(.in) if you edit Makefile.am # TODO: Resolve port-collision reliably (for multi-executor agents) # and enable the test for CI runs. Bonus for making it quieter. - if [ "${CANBUILD_NIT_TESTS-}" != yes ] ; then + if [ "${CANBUILD_NIT_TESTS-}" != no ] ; then CONFIG_OPTS+=("--enable-check-NIT") else echo "WARNING: Build agent does not say it can reliably 'make check-NIT'" >&2 From 4503347ae0d80a135aec4810d6b92ab9979a688a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 09:52:24 +0100 Subject: [PATCH 0311/1232] data/driver.list.in: update for APC CS500 (from 2004) [#1776] --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 5a742bee4d..75fe7cab55 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -79,6 +79,7 @@ "APC" "ups" "3" "Back-UPS XS 1000M (Back-UPS Pro 1000, Model BX1000M)" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/139 "APC" "ups" "3" "SMC2200BI-BR" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/557 "APC" "ups" "3" "Smart-UPS (USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "CS500" "USB" "usbhid-ups (limited data available)" # https://github.com/networkupstools/nut/issues/1776#issuecomment-1377784584 "APC" "ups" "1" "Back-UPS" "940-0095A/C cables" "genericups upstype=1" "APC" "ups" "1" "Back-UPS" "940-0020B/C cables" "genericups upstype=2" "APC" "ups" "1" "Back-UPS" "940-0023A cable" "genericups upstype=9" From 342cd723da635ef0e7d4c90fa023dae38a644691 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 09:54:43 +0100 Subject: [PATCH 0312/1232] drivers/apc-hid.c: comment 0xff86007c as "APCDelayBeforeReboot" vs "APCForceShutdown" uncertainty [#1796] --- drivers/apc-hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/apc-hid.c b/drivers/apc-hid.c index 3fa0894c2d..c7b11825e0 100644 --- a/drivers/apc-hid.c +++ b/drivers/apc-hid.c @@ -243,7 +243,7 @@ static usage_lkp_t apc_usage_lkp[] = { { "APCPanelTest", 0xff860072 }, /* FIXME: exploit */ { "APCShutdownAfterDelay", 0xff860076 }, /* FIXME: exploit */ { "APC_USB_FirmwareRevision", 0xff860079 }, /* FIXME: exploit */ - { "APCDelayBeforeReboot", 0xff86007c }, + { "APCDelayBeforeReboot", 0xff86007c }, /* WARNING: apcupsd maps this as APCForceShutdown... which one is right? */ { "APCDelayBeforeShutdown", 0xff86007d }, { "APCDelayBeforeStartup", 0xff86007e }, /* FIXME: exploit */ /* usage seen in dumps but unknown: From 8874942f7225a2e8e9ec6b20c38cc2eebd0f1015 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 16:25:58 +0100 Subject: [PATCH 0313/1232] m4/nut_check_python.m4, docs/configure.txt: detect not-specified PYTHON2/PYTHON3 from PYTHON first (if version is suitable) [#1787] --- docs/configure.txt | 5 ++ m4/nut_check_python.m4 | 109 +++++++++++++++++++++++++++++------------ 2 files changed, 84 insertions(+), 30 deletions(-) diff --git a/docs/configure.txt b/docs/configure.txt index f55a01dcae..273281de62 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -313,6 +313,11 @@ version if not specified by `--with-python` option or detected otherwise, you can provide the preferred version and implementation of Python 2 or 3 respectively. +Conversely, if neither of these configure options were specified, but some +`--with-python` program was specified or detected, and its report says it +has Python major version 2 or 3, then the versioned interpreter string would +point to that. + --with-nut_monitor Install the NUT-Monitor GUI application (depending on Python 2 or 3 version diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 604d9b185d..b9404567a7 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -18,8 +18,9 @@ AC_DEFUN([NUT_CHECK_PYTHON_DEFAULT], AS_IF([test x"$PYTHON3" != x], [PYTHON="$PYTHON3"]) AS_IF([test x"$PYTHON" = x], [AC_MSG_RESULT([none])], - [AC_MSG_RESULT([$PYTHON])] - ) + [AC_MSG_RESULT([$PYTHON]) + AC_MSG_WARN([A python program name was not specified during configuration, will default to '$PYTHON' (derived from --with-python2 or --with-python3 setting)]) + ]) ]) AS_IF([test -z "${PYTHON3}" && test x"${nut_with_python3}" = xyes], [ @@ -117,7 +118,42 @@ AC_DEFUN([NUT_CHECK_PYTHON2], PYTHON2="" PYTHON2_SITE_PACKAGES="" AS_CASE([${nut_with_python2}], - [auto|yes|""], [AC_CHECK_PROGS([PYTHON2], [python2 python2.7 python-2.7 python], [_python2_runtime])], + [auto|yes|""], [ + dnl Cross check --with-python results: + AS_CASE(["${PYTHON_VERSION_REPORT}"], + [*major=2,*], [ + PYTHON2="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + PYTHON2="`realpath "${PYTHON2}" 2>/dev/null`" && test -n "${PYTHON2}" || { + PYTHON2="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON2="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + fi + fi + fi + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + + dnl Only accept fully qualified names that refer to expected + dnl python version or quietly fall back to search below: + AS_CASE(["${PYTHON2}"], + [/usr/bin/env*], [PYTHON2=""], + [/*py*2.*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)])], + [/*py*2*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], + [PYTHON2=""]) + ]) + AS_IF([test x"${PYTHON2}" = x], [ + AC_CHECK_PROGS([PYTHON2], [python2 python2.7 python-2.7 python], [_python2_runtime]) + ]) + ], [no], [PYTHON2="no"], [PYTHON2="${nut_with_python2}"] ) @@ -126,19 +162,8 @@ AC_DEFUN([NUT_CHECK_PYTHON2], dnl if provided by the caller: AS_CASE([${PYTHON2}], [_python2_runtime], [ - dnl Cross check --with-python results: - AS_CASE(["${PYTHON_VERSION_REPORT}"], - [*major=2,*], [ - AS_CASE([${PYTHON}], - [/usr/bin/env*], [], - [/*py*2*], [PYTHON2="${PYTHON}"]) - ]) - AS_IF([test x"${PYTHON2}" = x_python2_runtime], [ - PYTHON2="/usr/bin/env python2" - AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (scripts will fail if that is not in PATH at run time)]) - ],[ - AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (specified or detected as --with-python setting)]) - ]) + PYTHON2="/usr/bin/env python2" + AC_MSG_WARN([A python2 program name was not detected during configuration, will default to '$PYTHON2' (scripts will fail if that is not in PATH at run time)]) ], [no], [], [/*" "*" "*], [ @@ -200,7 +225,42 @@ AC_DEFUN([NUT_CHECK_PYTHON3], PYTHON3="" PYTHON3_SITE_PACKAGES="" AS_CASE([${nut_with_python3}], - [auto|yes|""], [AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime])], + [auto|yes|""], [ + dnl Cross check --with-python results: + AS_CASE(["${PYTHON_VERSION_REPORT}"], + [*major=3,*], [ + PYTHON3="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + PYTHON3="`realpath "${PYTHON3}" 2>/dev/null`" && test -n "${PYTHON3}" || { + PYTHON3="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON3="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + fi + fi + fi + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + + dnl Only accept fully qualified names that refer to expected + dnl python version or quietly fall back to search below: + AS_CASE(["${PYTHON3}"], + [/usr/bin/env*], [PYTHON3=""], + [/*py*3.*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)])], + [/*py*3*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], + [PYTHON3=""]) + ]) + AS_IF([test x"${PYTHON3}" = x], [ + AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) + ]) + ], [no], [PYTHON3="no"], [PYTHON3="${nut_with_python3}"] ) @@ -209,19 +269,8 @@ AC_DEFUN([NUT_CHECK_PYTHON3], dnl if provided by the caller: AS_CASE([${PYTHON3}], [_python3_runtime], [ - dnl Cross check --with-python results: - AS_CASE(["${PYTHON_VERSION_REPORT}"], - [*major=3,*], [ - AS_CASE([${PYTHON}], - [/usr/bin/env*], [], - [/*py*3*], [PYTHON3="${PYTHON}"]) - ]) - AS_IF([test x"${PYTHON3}" = x_python3_runtime], [ - PYTHON3="/usr/bin/env python3" - AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (scripts will fail if that is not in PATH at run time)]) - ],[ - AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (specified or detected as --with-python setting)]) - ]) + PYTHON3="/usr/bin/env python3" + AC_MSG_WARN([A python3 program name was not detected during configuration, will default to '$PYTHON3' (scripts will fail if that is not in PATH at run time)]) ], [no], [], [/*" "*" "*], [ From fbb3ebde45482ba690d87617954f0bf6947c769d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 17:01:42 +0100 Subject: [PATCH 0314/1232] m4/nut_check_python.m4: for args like --with-python=python3 try to find build environment dictated pathname first, fall back to "env" second [#1787] Note: this does not apply to --with-python="prog args" as a bit too complex for now --- m4/nut_check_python.m4 | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index b9404567a7..92c2209a3a 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -71,7 +71,12 @@ AC_DEFUN([NUT_CHECK_PYTHON], AC_MSG_WARN([A python program name is not a single token (was specified with an argument?), so /usr/bin/env shebangs can be not reliable]) PYTHON="/usr/bin/env ${PYTHON}" ], - [*], [PYTHON="/usr/bin/env ${PYTHON}"] + [*], [ + myPYTHON="`command -v "${PYTHON}" 2>/dev/null`" && test -n "${myPYTHON}" && test -x "${myPYTHON}" \ + && PYTHON="${myPYTHON}" \ + || PYTHON="/usr/bin/env ${PYTHON}" + unset myPYTHON + ] ) PYTHON_VERSION_REPORT="" @@ -178,7 +183,12 @@ AC_DEFUN([NUT_CHECK_PYTHON2], AC_MSG_WARN([A python2 program name is not a single token (was specified with an argument?), so /usr/bin/env shebangs can be not reliable]) PYTHON2="/usr/bin/env ${PYTHON2}" ], - [*], [PYTHON2="/usr/bin/env ${PYTHON2}"] + [*], [ + myPYTHON="`command -v "${PYTHON2}" 2>/dev/null`" && test -n "${myPYTHON}" && test -x "${myPYTHON}" \ + && PYTHON2="${myPYTHON}" \ + || PYTHON2="/usr/bin/env ${PYTHON2}" + unset myPYTHON + ] ) PYTHON2_VERSION_REPORT="" @@ -285,7 +295,12 @@ AC_DEFUN([NUT_CHECK_PYTHON3], AC_MSG_WARN([A python3 program name is not a single token (was specified with an argument?), so /usr/bin/env shebangs can be not reliable]) PYTHON3="/usr/bin/env ${PYTHON3}" ], - [*], [PYTHON3="/usr/bin/env ${PYTHON3}"] + [*], [ + myPYTHON="`command -v "${PYTHON3}" 2>/dev/null`" && test -n "${myPYTHON}" && test -x "${myPYTHON}" \ + && PYTHON3="${myPYTHON}" \ + || PYTHON3="/usr/bin/env ${PYTHON3}" + unset myPYTHON + ] ) PYTHON3_VERSION_REPORT="" From 9d0b5a76084e764d2725deea6ee8fdda4970ab79 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Jan 2023 17:08:53 +0100 Subject: [PATCH 0315/1232] docs/configure.txt: warn about naming "relaxed" python interpreter versions [#1787] --- docs/configure.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 273281de62..259e36a2eb 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -329,6 +329,18 @@ Install the PyNUT module files for general consumption into "site-packages" location of the currently chosen Python interpreter(s): yes, no, auto. or dedicated as the required dependency of NUT-Monitor application (app). +[WARNING] +========= +The module files are installed into a particular Python version's location +such as `/usr/lib/python2.7/dist-packages` even if you specify a relaxed +or un-versioned interpreter like `python2` (which would be used in scripts +for the NUT-Monitor application and possible other consumers of the module). +If the preferred Python version in the deployed system changes later (so the +`python2` symlink for this example would point elsewhere) the module import +would become not resolvable for such consumers, until it is installed into +that other Python's "site-packages" location. +========= + Development files ~~~~~~~~~~~~~~~~~ From e4248aea76d146fcfb62d74cc9f1c52b7914dafc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 15:28:06 +0100 Subject: [PATCH 0316/1232] docs/configure.txt: warn about delivering for both Pythons if two are present [#1787] --- docs/configure.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 259e36a2eb..20441a2545 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -290,6 +290,13 @@ use `PYTHON2` and `PYTHON3` substitutions. They may be co-installed on the same system. A dispatcher shell script `NUT-Monitor` is used to launch the preferred (newest) or the only existing implementation. +Please note that by default NUT tries to make use of everything in your +build environment, so if both Python generation are detected -- the binding +module will be delivered into both, and two versions of NUT-Monitor GUI +application will be installed. If you want to avoid that behaviour on a +build system with both interpreters present, you can explicitly specify +to build e.g. `--without-python2 --with-python=/usr/bin/python-3.9`. + The settings below may be of particular interest to non-distribution packaging efforts with their own dedicated directory trees: From 5b4062276afd49eda2fdc37b9785aca3cc7e4b45 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 15:44:28 +0100 Subject: [PATCH 0317/1232] m4/nut_check_python.m4: add comments (and warning) about interpreter names without an exact version (2.* or 3.*) [#1787] --- m4/nut_check_python.m4 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 92c2209a3a..e59739ccb6 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -72,6 +72,7 @@ AC_DEFUN([NUT_CHECK_PYTHON], PYTHON="/usr/bin/env ${PYTHON}" ], [*], [ + dnl Note: no "realpath" here, see comment below myPYTHON="`command -v "${PYTHON}" 2>/dev/null`" && test -n "${myPYTHON}" && test -x "${myPYTHON}" \ && PYTHON="${myPYTHON}" \ || PYTHON="/usr/bin/env ${PYTHON}" @@ -79,6 +80,18 @@ AC_DEFUN([NUT_CHECK_PYTHON], ] ) + dnl Note: requesting e.g. "--with-python=python3" is valid, + dnl but would likely use a symlink that changes over time - + dnl and if `env` gets used, can resolve according to PATH + dnl (by default we try to bolt pathname here if resolvable, + dnl but do not unwrap the chain of symlinks like we do for + dnl versioned "--with-python2/3" due to their site-packages). + dnl For some use-cases, this lack of constraints may be + dnl deliberately desired; for others it is a "caveat emptor!" + AS_CASE(["${PYTHON}"], + [*2.*|*3.*], [], + [AC_MSG_WARN([A python program name without a specific version number was requested (may be a symlink prone to change over time): ${PYTHON}])]) + PYTHON_VERSION_REPORT="" AS_IF([test -n "${PYTHON}"], [ AS_IF([test x"`$PYTHON -c 'import sys; print (sys.version_info >= (2, 6))'`" = xTrue], From 9eaf61ae1f35ab65c38971f9bed9129c58ad3ec8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:03:15 +0100 Subject: [PATCH 0318/1232] m4/nut_check_python.m4: use pythonX-config if available to find the interpreter path [#1787] --- m4/nut_check_python.m4 | 102 +++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index e59739ccb6..b61a7c8073 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -140,34 +140,31 @@ AC_DEFUN([NUT_CHECK_PYTHON2], dnl Cross check --with-python results: AS_CASE(["${PYTHON_VERSION_REPORT}"], [*major=2,*], [ - PYTHON2="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" - PYTHON2="`realpath "${PYTHON2}" 2>/dev/null`" && test -n "${PYTHON2}" || { - PYTHON2="${PYTHON}" - PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" - if test -n "${PYTHON_CONFIG}" ; then - mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ - || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" - if test -f "${mySHEBANG_SCRIPT}" ; then - mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" - if test -n "${mySHEBANG}" ; then - PYTHON2="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ - && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + AS_CASE(["${PYTHON}"], + [/usr/bin/env*], [], + [/*py*2*], [ + PYTHON2="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + PYTHON2="`realpath "${PYTHON2}" 2>/dev/null`" && test -n "${PYTHON2}" || { + PYTHON2="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON2="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + fi + fi fi - fi - fi - unset mySHEBANG_SCRIPT - unset mySHEBANG - unset PYTHON_CONFIG - } - - dnl Only accept fully qualified names that refer to expected - dnl python version or quietly fall back to search below: - AS_CASE(["${PYTHON2}"], - [/usr/bin/env*], [PYTHON2=""], - [/*py*2.*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)])], - [/*py*2*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], - [PYTHON2=""]) - ]) + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)]) + ]) + ]) AS_IF([test x"${PYTHON2}" = x], [ AC_CHECK_PROGS([PYTHON2], [python2 python2.7 python-2.7 python], [_python2_runtime]) ]) @@ -252,34 +249,31 @@ AC_DEFUN([NUT_CHECK_PYTHON3], dnl Cross check --with-python results: AS_CASE(["${PYTHON_VERSION_REPORT}"], [*major=3,*], [ - PYTHON3="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" - PYTHON3="`realpath "${PYTHON3}" 2>/dev/null`" && test -n "${PYTHON3}" || { - PYTHON3="${PYTHON}" - PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" - if test -n "${PYTHON_CONFIG}" ; then - mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ - || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" - if test -f "${mySHEBANG_SCRIPT}" ; then - mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" - if test -n "${mySHEBANG}" ; then - PYTHON3="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ - && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + AS_CASE(["${PYTHON}"], + [/usr/bin/env*], [], + [/*py*3*], [ + PYTHON3="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + PYTHON3="`realpath "${PYTHON3}" 2>/dev/null`" && test -n "${PYTHON3}" || { + PYTHON3="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON3="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + fi + fi fi - fi - fi - unset mySHEBANG_SCRIPT - unset mySHEBANG - unset PYTHON_CONFIG - } - - dnl Only accept fully qualified names that refer to expected - dnl python version or quietly fall back to search below: - AS_CASE(["${PYTHON3}"], - [/usr/bin/env*], [PYTHON3=""], - [/*py*3.*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)])], - [/*py*3*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], - [PYTHON3=""]) - ]) + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)]) + ]) + ]) AS_IF([test x"${PYTHON3}" = x], [ AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) ]) From e93f638a972d244ab4a85cc9a5b03e58b1138d50 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:03:31 +0100 Subject: [PATCH 0319/1232] m4/nut_check_python.m4: add python 3.10 to searching list [#1787] --- m4/nut_check_python.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index b61a7c8073..22ed1f4f35 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -275,7 +275,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], ]) ]) AS_IF([test x"${PYTHON3}" = x], [ - AC_CHECK_PROGS([PYTHON3], [python3 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) + AC_CHECK_PROGS([PYTHON3], [python3 python3.10 python-3.10 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) ]) ], [no], [PYTHON3="no"], From 56cee473f6113464573cea5f4cc8a7f267145246 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:26:33 +0100 Subject: [PATCH 0320/1232] m4/nut_check_python.m4: if major version is known and expected, try to resolve the versioned interpreter starting from any initial name (check sanity afterwards, not before) [#1787] --- m4/nut_check_python.m4 | 98 ++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 22ed1f4f35..60cd8436fa 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -140,30 +140,33 @@ AC_DEFUN([NUT_CHECK_PYTHON2], dnl Cross check --with-python results: AS_CASE(["${PYTHON_VERSION_REPORT}"], [*major=2,*], [ - AS_CASE(["${PYTHON}"], - [/usr/bin/env*], [], - [/*py*2*], [ - PYTHON2="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" - PYTHON2="`realpath "${PYTHON2}" 2>/dev/null`" && test -n "${PYTHON2}" || { - PYTHON2="${PYTHON}" - PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" - if test -n "${PYTHON_CONFIG}" ; then - mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ - || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" - if test -f "${mySHEBANG_SCRIPT}" ; then - mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" - if test -n "${mySHEBANG}" ; then - PYTHON2="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ - && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" - fi - fi + PYTHON2="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" + PYTHON2="`realpath "${PYTHON2}" 2>/dev/null`" && test -n "${PYTHON2}" || { + PYTHON2="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON2="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON2}" || PYTHON2="${PYTHON}" fi - unset mySHEBANG_SCRIPT - unset mySHEBANG - unset PYTHON_CONFIG - } - AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)]) - ]) + fi + fi + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)]) + AS_IF([test "x${PYTHON}" = "x${PYTHON2}"], [ + AS_CASE(["${PYTHON2}"], + [/usr/bin/env*], [AC_MSG_WARN([Chosen python2 program name will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version)])], + [/*py*2.*], [], + [AC_MSG_WARN([Chosen python2 program name without a specific version number may be a symlink (prone to change over time)])]) + ]) + ]) ]) AS_IF([test x"${PYTHON2}" = x], [ AC_CHECK_PROGS([PYTHON2], [python2 python2.7 python-2.7 python], [_python2_runtime]) @@ -249,30 +252,33 @@ AC_DEFUN([NUT_CHECK_PYTHON3], dnl Cross check --with-python results: AS_CASE(["${PYTHON_VERSION_REPORT}"], [*major=3,*], [ - AS_CASE(["${PYTHON}"], - [/usr/bin/env*], [], - [/*py*3*], [ - PYTHON3="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" - PYTHON3="`realpath "${PYTHON3}" 2>/dev/null`" && test -n "${PYTHON3}" || { - PYTHON3="${PYTHON}" - PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" - if test -n "${PYTHON_CONFIG}" ; then - mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ - || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" - if test -f "${mySHEBANG_SCRIPT}" ; then - mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" - if test -n "${mySHEBANG}" ; then - PYTHON3="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ - && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" - fi - fi + PYTHON3="`${PYTHON} -c 'import sys; print(sys.executable);' 2>/dev/null`" && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" + PYTHON3="`realpath "${PYTHON3}" 2>/dev/null`" && test -n "${PYTHON3}" || { + PYTHON3="${PYTHON}" + PYTHON_CONFIG="`command -v "${PYTHON}-config" 2>/dev/null`" || PYTHON_CONFIG="" + if test -n "${PYTHON_CONFIG}" ; then + mySHEBANG_SCRIPT="`${PYTHON_CONFIG} --config-dir 2>/dev/null`/python-config.py" \ + || mySHEBANG_SCRIPT="${PYTHON_CONFIG}" + if test -f "${mySHEBANG_SCRIPT}" ; then + mySHEBANG="`head -1 "${mySHEBANG_SCRIPT}" | grep -E '^#!'`" || mySHEBANG="" + if test -n "${mySHEBANG}" ; then + PYTHON3="`echo "${mySHEBANG}" | sed 's,^#! *,,'`" \ + && test -n "${PYTHON3}" || PYTHON3="${PYTHON}" fi - unset mySHEBANG_SCRIPT - unset mySHEBANG - unset PYTHON_CONFIG - } - AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)]) - ]) + fi + fi + unset mySHEBANG_SCRIPT + unset mySHEBANG + unset PYTHON_CONFIG + } + AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)]) + AS_IF([test "x${PYTHON}" = "x${PYTHON3}"], [ + AS_CASE(["${PYTHON3}"], + [/usr/bin/env*], [AC_MSG_WARN([Chosen python3 program name will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version)])], + [/*py*3.*], [], + [AC_MSG_WARN([Chosen python3 program name without a specific version number may be a symlink (prone to change over time)])]) + ]) + ]) ]) AS_IF([test x"${PYTHON3}" = x], [ AC_CHECK_PROGS([PYTHON3], [python3 python3.10 python-3.10 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) From 7a3e5b335750ec31d225d88c379066d356004c68 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:30:11 +0100 Subject: [PATCH 0321/1232] m4/nut_check_python.m4: warn if using "PYTHON" via "/usr/bin/env" and not exact path [#1787] --- m4/nut_check_python.m4 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 60cd8436fa..250a449d0e 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -92,6 +92,9 @@ AC_DEFUN([NUT_CHECK_PYTHON], [*2.*|*3.*], [], [AC_MSG_WARN([A python program name without a specific version number was requested (may be a symlink prone to change over time): ${PYTHON}])]) + AS_CASE(["${PYTHON}"], + [/usr/bin/env*], [AC_MSG_WARN([A python program will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version): ${PYTHON}])]) + PYTHON_VERSION_REPORT="" AS_IF([test -n "${PYTHON}"], [ AS_IF([test x"`$PYTHON -c 'import sys; print (sys.version_info >= (2, 6))'`" = xTrue], From 4a191d7658045f019af8c9488a7f1992022ed6f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:34:07 +0100 Subject: [PATCH 0322/1232] m4/nut_check_python.m4: if resolved versioned interpreter filename is not a strict expected pattern, fall back to search [#1787] --- m4/nut_check_python.m4 | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 250a449d0e..197680e555 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -162,13 +162,14 @@ AC_DEFUN([NUT_CHECK_PYTHON2], unset mySHEBANG unset PYTHON_CONFIG } - AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)]) - AS_IF([test "x${PYTHON}" = "x${PYTHON2}"], [ - AS_CASE(["${PYTHON2}"], - [/usr/bin/env*], [AC_MSG_WARN([Chosen python2 program name will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version)])], - [/*py*2.*], [], - [AC_MSG_WARN([Chosen python2 program name without a specific version number may be a symlink (prone to change over time)])]) - ]) + + dnl Only accept fully qualified names that refer to expected + dnl python version or quietly fall back to search below: + AS_CASE(["${PYTHON2}"], + [/usr/bin/env*], [PYTHON2=""], + [/*py*2.*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)])], + [/*py*2*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], + [PYTHON2=""]) ]) ]) AS_IF([test x"${PYTHON2}" = x], [ @@ -274,13 +275,14 @@ AC_DEFUN([NUT_CHECK_PYTHON3], unset mySHEBANG unset PYTHON_CONFIG } - AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)]) - AS_IF([test "x${PYTHON}" = "x${PYTHON3}"], [ - AS_CASE(["${PYTHON3}"], - [/usr/bin/env*], [AC_MSG_WARN([Chosen python3 program name will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version)])], - [/*py*3.*], [], - [AC_MSG_WARN([Chosen python3 program name without a specific version number may be a symlink (prone to change over time)])]) - ]) + + dnl Only accept fully qualified names that refer to expected + dnl python version or quietly fall back to search below: + AS_CASE(["${PYTHON3}"], + [/usr/bin/env*], [PYTHON3=""], + [/*py*3.*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)])], + [/*py*3*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], + [PYTHON3=""]) ]) ]) AS_IF([test x"${PYTHON3}" = x], [ From 52765c34ce23360072a076a448bc9e03c77b622a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Jan 2023 16:51:59 +0100 Subject: [PATCH 0323/1232] configure.ac: report Python choices (if installing anything of it) [#1787] --- configure.ac | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.ac b/configure.ac index aaecde96d8..8c8b7cf544 100644 --- a/configure.ac +++ b/configure.ac @@ -1806,6 +1806,15 @@ AC_SUBST([nut_with_pynut_py], [${nut_with_pynut_py}]) AC_SUBST([nut_with_pynut_py2], [${nut_with_pynut_py2}]) AC_SUBST([nut_with_pynut_py3], [${nut_with_pynut_py3}]) +AS_IF([test "${nut_with_nut_monitor}" != no -o "${nut_with_pynut}" != no], [ + NUT_REPORT([Default Python interpreter ], [${PYTHON}]) + NUT_REPORT([Default Python site-packages], [${PYTHON_SITE_PACKAGES}]) + NUT_REPORT([Specific Python2 interpreter ], [${PYTHON2}]) + NUT_REPORT([Specific Python2 site-packages], [${PYTHON2_SITE_PACKAGES}]) + NUT_REPORT([Specific Python3 interpreter ], [${PYTHON3}]) + NUT_REPORT([Specific Python3 site-packages], [${PYTHON3_SITE_PACKAGES}]) +]) + dnl ---------------------------------------------------------------------- dnl checks related to --enable-cppcheck From 4482a8810e12499f2473888d8019c312473dda4a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 11:38:58 +0100 Subject: [PATCH 0324/1232] m4/nut_check_python.m4: use stricter conditions to check if PYTHONx values are invalid [#1787] --- m4/nut_check_python.m4 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 197680e555..58e998a02e 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -46,6 +46,7 @@ AC_DEFUN([NUT_CHECK_PYTHON], PYTHON="" PYTHON_SITE_PACKAGES="" + PYTHON_VERSION_REPORT="" AS_CASE([${nut_with_python}], [auto|yes|""], [AC_CHECK_PROGS([PYTHON], [python python3 python2], [_python_runtime])], [no], [PYTHON="no"], @@ -95,8 +96,7 @@ AC_DEFUN([NUT_CHECK_PYTHON], AS_CASE(["${PYTHON}"], [/usr/bin/env*], [AC_MSG_WARN([A python program will be resolved from PATH at run-time (PyNUT module may be not found if installed into site-packages of a specific version): ${PYTHON}])]) - PYTHON_VERSION_REPORT="" - AS_IF([test -n "${PYTHON}"], [ + AS_IF([test -n "${PYTHON}" && test "${PYTHON}" != "no"], [ AS_IF([test x"`$PYTHON -c 'import sys; print (sys.version_info >= (2, 6))'`" = xTrue], [PYTHON_VERSION_REPORT=" (`$PYTHON -c 'import sys; print (sys.version_info)'`)"], [AC_MSG_WARN([Version reported by ${PYTHON} was not suitable as python]) @@ -113,7 +113,7 @@ AC_DEFUN([NUT_CHECK_PYTHON], AC_MSG_CHECKING([python interpeter to call]) AC_MSG_RESULT([${PYTHON}${PYTHON_VERSION_REPORT}]) AC_SUBST([PYTHON], [${PYTHON}]) - AM_CONDITIONAL([HAVE_PYTHON], [test "${PYTHON}" != "no"]) + AM_CONDITIONAL([HAVE_PYTHON], [test -n "${PYTHON}" && test "${PYTHON}" != "no"]) AS_IF([test -n "${PYTHON}" && test "${PYTHON}" != "no"], [ export PYTHON AC_MSG_CHECKING([python site-packages location]) @@ -138,6 +138,7 @@ AC_DEFUN([NUT_CHECK_PYTHON2], PYTHON2="" PYTHON2_SITE_PACKAGES="" + PYTHON2_VERSION_REPORT="" AS_CASE([${nut_with_python2}], [auto|yes|""], [ dnl Cross check --with-python results: @@ -208,8 +209,7 @@ AC_DEFUN([NUT_CHECK_PYTHON2], ] ) - PYTHON2_VERSION_REPORT="" - AS_IF([test -n "${PYTHON2}"], [ + AS_IF([test -n "${PYTHON2}" && test "${PYTHON2}" != "no"], [ AS_IF([test x"`$PYTHON2 -c 'import sys; print (sys.version_info >= (2, 6) and sys.version_info < (3, 0))'`" = xTrue], [PYTHON2_VERSION_REPORT=" (`$PYTHON2 -c 'import sys; print (sys.version_info)'`)"], [AC_MSG_WARN([Version reported by ${PYTHON2} was not suitable as python2]) @@ -226,7 +226,7 @@ AC_DEFUN([NUT_CHECK_PYTHON2], AC_MSG_CHECKING([python2 interpeter to call]) AC_MSG_RESULT([${PYTHON2}${PYTHON2_VERSION_REPORT}]) AC_SUBST([PYTHON2], [${PYTHON2}]) - AM_CONDITIONAL([HAVE_PYTHON2], [test "${PYTHON2}" != "no"]) + AM_CONDITIONAL([HAVE_PYTHON2], [test -n "${PYTHON2}" && test "${PYTHON2}" != "no"]) AS_IF([test -n "${PYTHON2}" && test "${PYTHON2}" != "no"], [ export PYTHON2 AC_MSG_CHECKING([python2 site-packages location]) @@ -251,6 +251,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], PYTHON3="" PYTHON3_SITE_PACKAGES="" + PYTHON3_VERSION_REPORT="" AS_CASE([${nut_with_python3}], [auto|yes|""], [ dnl Cross check --with-python results: @@ -321,8 +322,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], ] ) - PYTHON3_VERSION_REPORT="" - AS_IF([test -n "${PYTHON3}"], [ + AS_IF([test -n "${PYTHON3}" && test "${PYTHON3}" != "no"], [ AS_IF([test x"`$PYTHON3 -c 'import sys; print (sys.version_info >= (3, 0))'`" = xTrue], [PYTHON3_VERSION_REPORT=" (`$PYTHON3 -c 'import sys; print (sys.version_info)'`)"], [AC_MSG_WARN([Version reported by ${PYTHON3} was not suitable as python3]) @@ -339,7 +339,7 @@ AC_DEFUN([NUT_CHECK_PYTHON3], AC_MSG_CHECKING([python3 interpeter to call]) AC_MSG_RESULT([${PYTHON3}${PYTHON3_VERSION_REPORT}]) AC_SUBST([PYTHON3], [${PYTHON3}]) - AM_CONDITIONAL([HAVE_PYTHON3], [test "${PYTHON3}" != "no"]) + AM_CONDITIONAL([HAVE_PYTHON3], [test -n "${PYTHON3}" && test "${PYTHON3}" != "no"]) AS_IF([test -n "${PYTHON3}" && test "${PYTHON3}" != "no"], [ export PYTHON3 AC_MSG_CHECKING([python3 site-packages location]) From b1d23d771fd5f6d70b14724aee99ee4895be40dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 12:14:50 +0100 Subject: [PATCH 0325/1232] m4/nut_check_python.m4: fix copy-paste typo in autoconf m4 markup [#1787] --- m4/nut_check_python.m4 | 2 -- 1 file changed, 2 deletions(-) diff --git a/m4/nut_check_python.m4 b/m4/nut_check_python.m4 index 58e998a02e..995a3e7c97 100644 --- a/m4/nut_check_python.m4 +++ b/m4/nut_check_python.m4 @@ -171,7 +171,6 @@ AC_DEFUN([NUT_CHECK_PYTHON2], [/*py*2.*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version)])], [/*py*2*], [AC_MSG_WARN([A python2 program name was not specified during configuration, will default to '$PYTHON2' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], [PYTHON2=""]) - ]) ]) AS_IF([test x"${PYTHON2}" = x], [ AC_CHECK_PROGS([PYTHON2], [python2 python2.7 python-2.7 python], [_python2_runtime]) @@ -284,7 +283,6 @@ AC_DEFUN([NUT_CHECK_PYTHON3], [/*py*3.*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version)])], [/*py*3*], [AC_MSG_WARN([A python3 program name was not specified during configuration, will default to '$PYTHON3' (derived from --with-python setting which has a suitable version, but without a specific version number - so may be a symlink prone to change over time)])], [PYTHON3=""]) - ]) ]) AS_IF([test x"${PYTHON3}" = x], [ AC_CHECK_PROGS([PYTHON3], [python3 python3.10 python-3.10 python3.9 python-3.9 python3.7 python-3.7 python3.6 python-3.6 python3.5 python-3.5 python], [_python3_runtime]) From 4b4032d341bc5f4c62f4e3640ec25efc439447f2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 12:38:21 +0100 Subject: [PATCH 0326/1232] m4/nut_report_feature.m4: introduce NUT_REPORT_PATH_INTEGRATIONS and NUT_REPORT_SETTING_PATH_INTEGRATIONS chapter [#1708] --- m4/nut_report_feature.m4 | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index d57b40cae7..87a565722f 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -41,6 +41,13 @@ AC_DEFUN([NUT_REPORT_PATH], NUT_REPORT_FILE([$1], [$2], [2], "NUT Paths:") ]) +AC_DEFUN([NUT_REPORT_PATH_INTEGRATIONS], +[ + dnl arg#1 = description (summary) + dnl arg#2 = value + NUT_REPORT_FILE([$1], [$2], [3], "NUT Paths for third-party integrations:") +]) + AC_DEFUN([NUT_REPORT_FEATURE], [ dnl arg#1 = summary/config.log description @@ -86,6 +93,20 @@ AC_DEFUN([NUT_REPORT_SETTING_PATH], AC_DEFINE_UNQUOTED($2, $3, $4) ]) +AC_DEFUN([NUT_REPORT_SETTING_PATH_INTEGRATIONS], +[ + dnl arg#1 = summary/config.log description + dnl arg#2 = autoconf varname + dnl arg#3 = value + dnl arg#4 = longer description (autoconf comment) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT_PATH_INTEGRATIONS([$1], [$3]) + + dnl Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) +]) + AC_DEFUN([NUT_REPORT_TARGET], [ dnl arg#1 = autoconf varname From 9d74b626e5b7d8735f1ec8bda6ea8975b1777f6c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 12:42:31 +0100 Subject: [PATCH 0327/1232] configure.ac: rearrange Python interpreter and path reporting [#1787, #1708] --- configure.ac | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 8c8b7cf544..5bd2fb518f 100644 --- a/configure.ac +++ b/configure.ac @@ -1807,12 +1807,21 @@ AC_SUBST([nut_with_pynut_py2], [${nut_with_pynut_py2}]) AC_SUBST([nut_with_pynut_py3], [${nut_with_pynut_py3}]) AS_IF([test "${nut_with_nut_monitor}" != no -o "${nut_with_pynut}" != no], [ - NUT_REPORT([Default Python interpreter ], [${PYTHON}]) - NUT_REPORT([Default Python site-packages], [${PYTHON_SITE_PACKAGES}]) - NUT_REPORT([Specific Python2 interpreter ], [${PYTHON2}]) - NUT_REPORT([Specific Python2 site-packages], [${PYTHON2_SITE_PACKAGES}]) - NUT_REPORT([Specific Python3 interpreter ], [${PYTHON3}]) - NUT_REPORT([Specific Python3 site-packages], [${PYTHON3_SITE_PACKAGES}]) + NUT_REPORT([use default Python interpreter], [${PYTHON}]) + NUT_REPORT([use specific Python2 interpreter], [${PYTHON2}]) + NUT_REPORT([use specific Python3 interpreter], [${PYTHON3}]) + + NUT_REPORT_SETTING_PATH_INTEGRATIONS([Default Python interpreter site-packages], + PYTHON_SITE_PACKAGES, "${PYTHON_SITE_PACKAGES}", + [Python site-packages installation path for default Python interpreter]) + + NUT_REPORT_SETTING_PATH_INTEGRATIONS([Specific Python2 interpreter site-packages], + PYTHON2_SITE_PACKAGES, "${PYTHON2_SITE_PACKAGES}", + [Python site-packages installation path for specific Python2 interpreter]) + + NUT_REPORT_SETTING_PATH_INTEGRATIONS([Specific Python3 interpreter site-packages], + PYTHON3_SITE_PACKAGES, "${PYTHON3_SITE_PACKAGES}", + [Python site-packages installation path for specific Python3 interpreter]) ]) dnl ---------------------------------------------------------------------- From 92bb1696d05f6483f02241981d779f63e2f5ce67 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 13:00:27 +0100 Subject: [PATCH 0328/1232] configure.ac: simplify reporting of Python site-packages location [#1787, #1708] --- configure.ac | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 5bd2fb518f..ce1f24a3d9 100644 --- a/configure.ac +++ b/configure.ac @@ -1811,17 +1811,15 @@ AS_IF([test "${nut_with_nut_monitor}" != no -o "${nut_with_pynut}" != no], [ NUT_REPORT([use specific Python2 interpreter], [${PYTHON2}]) NUT_REPORT([use specific Python3 interpreter], [${PYTHON3}]) - NUT_REPORT_SETTING_PATH_INTEGRATIONS([Default Python interpreter site-packages], - PYTHON_SITE_PACKAGES, "${PYTHON_SITE_PACKAGES}", - [Python site-packages installation path for default Python interpreter]) + NUT_REPORT_PATH_INTEGRATIONS([Default Python interpreter site-packages], + ["${PYTHON_SITE_PACKAGES}"]) - NUT_REPORT_SETTING_PATH_INTEGRATIONS([Specific Python2 interpreter site-packages], - PYTHON2_SITE_PACKAGES, "${PYTHON2_SITE_PACKAGES}", - [Python site-packages installation path for specific Python2 interpreter]) + NUT_REPORT_PATH_INTEGRATIONS([Specific Python2 interpreter site-packages], + ["${PYTHON2_SITE_PACKAGES}"]) - NUT_REPORT_SETTING_PATH_INTEGRATIONS([Specific Python3 interpreter site-packages], - PYTHON3_SITE_PACKAGES, "${PYTHON3_SITE_PACKAGES}", - [Python site-packages installation path for specific Python3 interpreter]) + NUT_REPORT_PATH_INTEGRATIONS([Specific Python3 interpreter site-packages], + ["${PYTHON3_SITE_PACKAGES}"]) + dnl # Python site-packages installation path for specific Python3 interpreter ]) dnl ---------------------------------------------------------------------- From 12dc90abc660be04d07cf8b5706492c37169e5cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 14:44:49 +0100 Subject: [PATCH 0329/1232] configure.ac: report installation paths for optional third-party integrations [#1708, #1668] --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index ce1f24a3d9..6533c37bc5 100644 --- a/configure.ac +++ b/configure.ac @@ -2463,6 +2463,7 @@ AC_ARG_WITH(pkgconfig-dir, ], []) if test -n "${pkgconfigdir}"; then AC_MSG_RESULT(using ${pkgconfigdir}) + NUT_REPORT_PATH_INTEGRATIONS([pkg-config *.pc directory], ["${pkgconfigdir}"]) else AC_MSG_RESULT(no) fi @@ -2632,6 +2633,7 @@ if test "${systemdsystemunitdir}" = "auto" ; then systemdsystemunitdir=""; fi if test -n "${systemdsystemunitdir}"; then have_systemd="yes" AC_MSG_RESULT(using ${systemdsystemunitdir}) + NUT_REPORT_PATH_INTEGRATIONS([Service units for systemd], ["${systemdsystemunitdir}"]) else have_systemd="no" AC_MSG_RESULT(no) @@ -2674,6 +2676,7 @@ fi if test "${systemdshutdowndir}" = "auto" ; then systemdshutdowndir=""; fi if test -n "${systemdshutdowndir}"; then AC_MSG_RESULT(using ${systemdshutdowndir}) + NUT_REPORT_PATH_INTEGRATIONS([Shutdown hooks for systemd], ["${systemdshutdowndir}"]) else AC_MSG_RESULT(no) fi @@ -2706,6 +2709,7 @@ esac if test "${systemdtmpfilesdir}" = "auto" ; then systemdtmpfilesdir=""; fi if test -n "${systemdtmpfilesdir}"; then AC_MSG_RESULT(using ${systemdtmpfilesdir}) + NUT_REPORT_PATH_INTEGRATIONS([Systemd-tmpfiles configs], ["${systemdtmpfilesdir}"]) else AC_MSG_RESULT(no) fi @@ -2958,6 +2962,7 @@ AC_ARG_WITH(augeas-lenses-dir, ], []) if test -n "${auglensdir}"; then AC_MSG_RESULT(using ${auglensdir}) + NUT_REPORT_PATH_INTEGRATIONS([Augeas lenses directory], ["${auglensdir}"]) else AC_MSG_RESULT(no) fi @@ -2996,6 +3001,7 @@ AC_ARG_WITH(hotplug-dir, ], []) if test -n "${hotplugdir}"; then AC_MSG_RESULT(using ${hotplugdir}) + NUT_REPORT_PATH_INTEGRATIONS([Hotplug rules directory], ["${hotplugdir}"]) else AC_MSG_RESULT(no) fi @@ -3032,6 +3038,7 @@ AC_ARG_WITH(udev-dir, ], []) if test -n "${udevdir}"; then AC_MSG_RESULT(using ${udevdir}) + NUT_REPORT_PATH_INTEGRATIONS([Udev rules directory], ["${udevdir}"]) else AC_MSG_RESULT(no) fi @@ -3070,6 +3077,7 @@ AC_ARG_WITH(devd-dir, ], []) if test -n "${devddir}"; then AC_MSG_RESULT(using ${devddir}) + NUT_REPORT_PATH_INTEGRATIONS([FreeBSD devd rules directory], ["${devddir}"]) else AC_MSG_RESULT(no) fi From a060645d132f2091db438fc441f0d27c26c14516 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 14:49:49 +0100 Subject: [PATCH 0330/1232] configure.ac: report enabling SMF support (consistent vs. reporting systemd already) [#1708] --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 6533c37bc5..96ba02a3ea 100644 --- a/configure.ac +++ b/configure.ac @@ -2561,6 +2561,7 @@ if test x"$solarissmf" = xauto ; then fi AC_MSG_RESULT([${solarissmf}]) AM_CONDITIONAL(WITH_SOLARIS_SMF, test x"$solarissmf" = x"yes") +NUT_REPORT([consider basic SMF support], [${solarissmf}]) AC_MSG_CHECKING(whether to install Solaris SVR4 (legacy) init-script files) From 463d4cea7bedab003ad5ccc2d3d46e2c294f24cd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 14:54:54 +0100 Subject: [PATCH 0331/1232] configure.ac: evaluate pkgconfigdir into a real pathname Have an option of NOT keeping/using literally '${libdir}/pkgconfig' that needs further evaluation --- configure.ac | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0bd0f1af6d..6807ffecfd 100644 --- a/configure.ac +++ b/configure.ac @@ -2460,8 +2460,19 @@ AC_ARG_WITH(pkgconfig-dir, ;; esac ], []) + +dnl Note: currently pkgconfigdir='${libdir}/pkgconfig' literally +dnl goes into lib/Makefile.am substitution for pkgconfig_DATA. +dnl By default we get ${libdir}/pkgconfig and below expand it to +dnl => ${exec_prefix}/lib/pkgconfig => ${prefix}/lib/pkgconfig => real path +conftemp="${pkgconfigdir}" +eval conftemp=\"${conftemp}\" +eval conftemp=\"${conftemp}\" +eval conftemp=\"${conftemp}\" +PKGCONFIGDIR="${conftemp}" + if test -n "${pkgconfigdir}"; then - AC_MSG_RESULT(using ${pkgconfigdir}) + AC_MSG_RESULT(using ${pkgconfigdir} => ${conftemp}) else AC_MSG_RESULT(no) fi @@ -3432,6 +3443,7 @@ AC_SUBST(CONFPATH) AC_SUBST(POWERDOWNFLAG) AC_SUBST(BINDIR) AC_SUBST(LIBDIR) +AC_SUBST(PKGCONFIGDIR) AC_SUBST(NUT_DATADIR, [`eval echo "${NUT_DATADIR}"`]) AC_SUBST(NUT_LIBEXECDIR, [`eval echo "${LIBEXECDIR}"`]) AC_SUBST(DRVPATH) From d90badbef86bfd9751da64c6ace55082666098fe Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 15:16:33 +0100 Subject: [PATCH 0332/1232] drivers/libusb{0,1}.c: clarify expected/got byte amounts (fix typo) [#1797] --- drivers/libusb0.c | 4 ++-- drivers/libusb1.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 5b3e87e6ab..4fd12c7bd6 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -466,9 +466,9 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "Unable to get HID descriptor (%s)", usb_strerror()); } else if (res < 9) { - upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 8, res); + upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 9, res); } else { - + upsdebugx(2, "Retrieved HID descriptor (expected %d, got %d)", 9, res); upsdebug_hex(3, "HID descriptor, method 1", buf, 9); rdlen1 = ((uint8_t)buf[7]) | (((uint8_t)buf[8]) << 8); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 84aa4f23d9..048aa7c510 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -515,9 +515,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "Unable to get HID descriptor (%s)", libusb_strerror((enum libusb_error)res)); } else if (res < 9) { - upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 8, res); + upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 9, res); } else { - + upsdebugx(2, "Retrieved HID descriptor (expected %d, got %d)", 9, res); upsdebug_hex(3, "HID descriptor, method 1", buf, 9); rdlen1 = ((uint8_t)buf[7]) | (((uint8_t)buf[8]) << 8); From 3cf7cc722e8207a8609c23965a8d445442c9f9ff Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 15:28:41 +0100 Subject: [PATCH 0333/1232] UPGRADING: clarify improvements for "duplicate" USB device handling in NUT 2.8.1 [#1763, #1766, #1756, #1790] --- UPGRADING | 18 ++++++++++++++++++ docs/nut.dict | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/UPGRADING b/UPGRADING index 027a552fc3..701d8412c4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -19,6 +19,24 @@ Changes from 2.8.0 to 2.8.1 - PLANNED: Keep track of any further API clean-up? +- Several improvements regarding simultaneous support of USB devices that + were previously deemed "identical" and so NUT driver instances did not + start for all of them: + + * Some more drivers should now use the common USB device matching logic + and the 7 `ups.conf` options for that [#1763], and man pages were + updated to reflect that [#1766]; + + * The `nut-scanner` tool should suggest these options in its generated + device configuration [#1790]: hopefully these would now suffice for + sufficiently unique combinations; + + * The common USB matching logic was updated with an `allow_duplicates` + flag (caveat emptor!) which may help monitor several related no-name + devices on systems that do not discern "bus" and "device" values + (although without knowing reliably which one is which... sometimes it + is better than nothing) [#1756]. + - Work on NUT for Windows branch led to situation-specific definitions of what in POSIX code was all "file descriptors" (an `int` type). Now such entities are named `TYPE_FD`, `TYPE_FD_SER` or `TYPE_FD_SOCK` with some diff --git a/docs/nut.dict b/docs/nut.dict index 9fb58934c6..7781673710 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3075 utf-8 +personal_ws-1.1 en 3076 utf-8 AAS ABI ACFAIL @@ -1815,6 +1815,7 @@ egrep ei el emacs +emptor endchar enddate endian From 010f285ddb8e1abf6e3437526fb8cede02842a5d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 15:37:24 +0100 Subject: [PATCH 0334/1232] scripts/systemd/nut-{server,monitor,driver@}.service.in: clarify network-online.target dependency [#749] --- scripts/systemd/nut-driver@.service.in | 6 ++++-- scripts/systemd/nut-monitor.service.in | 6 ++++-- scripts/systemd/nut-server.service.in | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 413750813a..2b903ca49a 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -27,8 +27,10 @@ PartOf=nut-driver.target # and typically by the time the box gets an IP address, the driver # is still retrying to start and will succeed. # Extending the unit does not require *this* file to be edited, you -# can instead drop in an additional piece of configuration, e.g. add -# a `/etc/systemd/system/nut-driver@.service.d/network.conf` with: +# can instead drop in an additional piece of configuration, e.g. to +# require that a NUT driver only starts after external networking +# is configured (usable IP addresses appear in the system) you can +# add a `/etc/systemd/system/nut-driver@.service.d/network.conf` with: # [Unit] # Requires=network-online.target # After=network-online.target diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 5b22148ae8..b8a86bdb1a 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -9,8 +9,10 @@ After=local-fs.target network.target nut-server.service # would not abort if that attempt fails for whatever reason. Wants=nut-server.service # Extending the unit does not require *this* file to be edited, you -# can instead drop in an additional piece of configuration, e.g. add -# a `/etc/systemd/system/nut-monitor.service.d/network.conf` with: +# can instead drop in an additional piece of configuration, e.g. to +# require the monitoring client to only start after external networking +# is configured (usable IP addresses appear in the system) you can +# add a `/etc/systemd/system/nut-monitor.service.d/network.conf` with: # [Unit] # Requires=network-online.target # After=network-online.target diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 0a377c23ab..7a3f1096db 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -8,8 +8,10 @@ Wants=nut-driver.target # The `upsd` is a networked service (even if bound to a `localhost`) # so it requires that the OS has some notion of networking already. # Extending the unit does not require *this* file to be edited, you -# can instead drop in an additional piece of configuration, e.g. add -# a `/etc/systemd/system/nut-server.service.d/network.conf` with: +# can instead drop in an additional piece of configuration, e.g. to +# require that NUT data server only starts after external networking +# is configured (usable IP addresses appear in the system) you can +# add a `/etc/systemd/system/nut-server.service.d/network.conf` with: # [Unit] # Requires=network-online.target # After=network-online.target From a37ed92cde62d4ff3a6989bd9916792cba61aa74 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 23:26:50 +0100 Subject: [PATCH 0335/1232] docs/config-prereqs.txt: update for CentOS6 --- docs/config-prereqs.txt | 53 +++++++++++++++++++++++++++++++++++++---- docs/nut.dict | 6 +++-- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 3b40f4736f..3e90baffa5 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -208,14 +208,20 @@ NOTE: For Jenkins agents, also need to `apt-get install openjdk-11-jdk-headless` You may have to ensure that `/proc` is mounted in the target chroot (or do this from the running container). -CentOS 7 -~~~~~~~~ +CentOS 6 and 7 +~~~~~~~~~~~~~~ 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. +For CI farm container setup, prepared root filesystem archives from +http://download.proxmox.com/images/system/ worked sufficiently well. + +Prepare CentOS repository mirrors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + For CentOS 7 it seems that not all repositories are equally good; some of the software below is only served by EPEL (Extra Packages for Enterprise Linux), as detailed at: @@ -237,12 +243,47 @@ file (as the aged distributions become less served by mirrors), such as: # lines, and comment away the mirrorlist= lines (if yum hiccups otherwise) ------ +For systemd support on CentOS 7 (no equivalent found for CentOS 6), +you can use backports repository below: +------ +:; curl https://copr.fedorainfracloud.org/coprs/jsynacek/systemd-backports-for-centos-7 + > /etc/yum.repos.d/systemd-backports-for-centos-7.repo +------ + +For CentOS 6 (the oldest I could try) the situation is similar, with sites like +https://www.getpagespeed.com/server-setup/how-to-fix-yum-after-centos-6-went-eol +detailing how to replace `/etc/yum.repos.d/` contents (you can wholesale rename +the existing directory and populate a new one with `curl` downloads from the +article), and additional key trust for EPEL packages: +------ +:; yum install https://dl.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm +------ + +Set up CentOS packages for NUT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Instructions below apply to both CentOS 6 and 7 (a few nuances for 6 commented). + General developer system helpers mentioned in link:ci-farm-lxc-setup.txt[]: ------ :; yum update :; yum install \ - sudo vim mc p7zip pigz pbzip2 + sudo vim mc p7zip pigz pbzip2 tar +------ + +To have SSH access to the build VM/Container, you may have to install and +enable it: +------ +:; yum install \ + openssh-server openssh-clients + +:; chkconfig sshd on +:; service sshd start + +# If there are errors loading generated host keys, remove mentioned files +# including the one with .pub extension and retry with: +#:; service sshd restart ------ NOTE: Below we request to install generic `python` per system defaults. @@ -273,6 +314,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. # :; yum install python3 python3-3.6.8 # 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 spell-checking, highly recommended if you would propose pull requests: :; yum install \ @@ -286,7 +328,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. :; yum install \ gd-devel -# Optionally for sd_notify integration: +# Optionally for sd_notify integration (on CentOS 7+, not on 6): :; yum install \ systemd-devel @@ -328,7 +370,8 @@ other described environments by adding a symlink `/usr/lib/ccache`: :; ln -s ../lib64/ccache/ "$ALTROOT"/usr/lib/ ------ -NOTE: For Jenkins agents, also need to `yum install java-11-openjdk-headless`. +NOTE: For Jenkins agents, also need to `yum install java-11-openjdk-headless` +(not available for CentOS 6). Arch Linux ~~~~~~~~~~ diff --git a/docs/nut.dict b/docs/nut.dict index 9fb58934c6..a1bbf845fa 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3075 utf-8 +personal_ws-1.1 en 3077 utf-8 AAS ABI ACFAIL @@ -1517,6 +1517,7 @@ backends backgrounding backport backported +backports backupspro badpassword baseurl @@ -1626,6 +1627,7 @@ charset checksum chgrp chipset +chkconfig chmod chown chr @@ -2821,8 +2823,8 @@ testtime testuser textproc th -timehead timeframe +timehead timeline timername timestamp From 747ecbe2dcb787c86996896a0282b9e459543b5c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Jan 2023 23:53:54 +0100 Subject: [PATCH 0336/1232] configure.ac, m4/ax_check_compile_flag.m4: relax minimum autoconf to 2.63 (checked on CentOS6) --- configure.ac | 4 +++- m4/ax_check_compile_flag.m4 | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0bd0f1af6d..3707889126 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,7 @@ AM_INIT_AUTOMAKE([subdir-objects]) dnl we need Autoconf 2.61 or better to enable features of Posix that are extensions to C dnl (and actually 2.64 or better for m4/ax_check_compile_flag.m4 when it is sourced) +dnl UPDATE: As tested on CentOS 6, its "autoconf-2.63-5.1.el6.noarch" also suffices. AC_MSG_CHECKING(for autoconf macro to enable system extensions) m4_version_prereq(2.61, [ AC_MSG_RESULT(yes) @@ -27,7 +28,8 @@ m4_version_prereq(2.61, [ AC_MSG_RESULT(no) ]) -AC_PREREQ([2.64]) +AC_PREREQ([2.63]) +dnl #AC_PREREQ([2.64]) dnl Use "./configure --enable-maintainer-mode" to keep Makefile.in and Makefile dnl in sync after Git updates. diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 index a72fc05246..9316a72448 100644 --- a/m4/ax_check_compile_flag.m4 +++ b/m4/ax_check_compile_flag.m4 @@ -40,7 +40,10 @@ #serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +[ +dnl UPDATE: As tested on CentOS 6, its "autoconf-2.63-5.1.el6.noarch" also suffices. +AC_PREREQ(2.63) +dnl #AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS From be7fcb0dc4cb6cbd4c34c53ed1e6427634eae98a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 00:12:51 +0100 Subject: [PATCH 0337/1232] autogen.sh: ensure quieter perl on system with invalid locale --- autogen.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/autogen.sh b/autogen.sh index 6e9e89cfcb..0f330ad4f7 100755 --- a/autogen.sh +++ b/autogen.sh @@ -4,6 +4,18 @@ # in a buildable state # NOTE: uses cumbersome dumbest-possible shell syntax for extra portability +# perl tends to complain if locale is not set (or its files are absent) +if [ -z "${LANG-}" ]; then + LANG="C" + export LANG +fi + +if [ -z "${LC_ALL-}" ] ; then + LC_ALL="C" + export LC_ALL +fi + + if [ -n "${PYTHON-}" ] ; then # May be a name/path of binary, or one with args - check both (command -v "$PYTHON") \ From 431334af93e2dc69fb018164e4ae669ee336dd9f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 00:17:28 +0100 Subject: [PATCH 0338/1232] docs/config-prereqs.txt: clarify lack of libusb-1.0 in CentOS 6 --- docs/config-prereqs.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 3e90baffa5..21159a70ab 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -290,7 +290,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. +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, it seems that development against libi2c/smbus is not supported. Neither the suitable devel packages were found, nor i2c-based @@ -332,7 +333,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. :; yum install \ systemd-devel -# NOTE: "libusbx" is the CentOS way of naming "libusb-1.0" +# 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" :; yum install \ cppunit-devel \ From eb837c3bfd725c85a360095daae7c71c777ac4e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 09:10:37 +0100 Subject: [PATCH 0339/1232] drivers/upsdrvctl.c: whitespace fix in usage() --- drivers/upsdrvctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 4bb4e2e3ed..bd1acac2b5 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -526,8 +526,8 @@ static void help(const char *progname) printf(" -r drivers will chroot to \n"); printf(" -t testing mode - prints actions without doing them\n"); printf(" -u drivers started will switch from root to \n"); - printf(" -D raise debugging level\n"); - printf(" -d pass debugging level from upsdrvctl to driver\n"); + printf(" -D raise debugging level\n"); + printf(" -d pass debugging level from upsdrvctl to driver\n"); printf(" start start all UPS drivers in ups.conf\n"); printf(" start only start driver for UPS \n"); printf(" stop stop all UPS drivers in ups.conf\n"); From 55b179da862593ae32e1d93910b524c01dad6d34 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 11:50:28 +0100 Subject: [PATCH 0340/1232] drivers/upsdrvctl.c: add "-F"/"-B" args for drivers to be fore/back-grounded explicitly [#1759] --- NEWS | 7 ++++++ docs/man/upsdrvctl.txt | 13 +++++++++++ drivers/upsdrvctl.c | 50 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 45e3473bf2..17f42d52ce 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,13 @@ https://github.com/networkupstools/nut/milestone/8 v2.8.1 [#1420] * Fixed building of NUT man pages when just a few drivers are selected by `configure` script for custom builds [#1467] + * Now that `upsdrvctl` can pass debugging level through to the launched + driver(s), they would by default stay in the foreground. This can + complicate (or simplify, when intentional) the management of service + instances. Now there are explicit `upsdrvctl` options for choosing + this (`-F`/`-B`), although default behavior is retained. Note that + foregrounding and mass-management loop to start all drivers (without + specifying the single device) do not play well together [#1759] - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 24bc90366b..c2c86cdcf6 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -60,6 +60,19 @@ Raise the debug level. Use this multiple times for additional details. *-d*:: Pass the selected debug level from `upsdrvctl` to launched drivers. +Note that by default for NUT daemons, enabled debugging means running +in foreground mode; you can specify *-B* additionally to avoid that. + +*-F*:: +Driver will run in the foreground (not fork away from the `upsdrvctl` +process), regardless of debugging settings. This may be counterproductive +if you start "everything" (do not specify an *ups* argument) as the loop +would never proceed beyond the first device in the list, so `upsdrvctl` +will warn about such situations. + +*-B*:: +Drivers will run in the background, regardless of debugging settings, +as set by *-D* and passed-through by *-d* options. COMMANDS -------- diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index bd1acac2b5..8eaf8268b8 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -69,6 +69,7 @@ static char *pt_root = NULL, *pt_user = NULL; /* flag to pass nut_debug_level to launched drivers (as their -D... args) */ static int nut_debug_level_passthrough = 0; +static int nut_foreground_passthrough = -1; void do_upsconf_args(char *upsname, char *var, char *val) { @@ -395,7 +396,7 @@ static void forkexec(char *const argv[], const ups_t *ups) static void start_driver(const ups_t *ups) { - char *argv[9]; + char *argv[10]; char dfn[SMALLBUF], dbg[SMALLBUF]; int ret, arg = 0; int initial_exec_error = exec_error, drv_maxretry = maxretry; @@ -471,6 +472,23 @@ static void start_driver(const ups_t *ups) argv[arg++] = dbg; } + /* Default: -1, FG/BG depends on debugging level */ + /* send_all_drivers() also warns if got many drivers to handle + * and foreground mode - it won't loop really */ + if (nut_foreground_passthrough == 0) { + argv[arg++] = (char *)"-B"; /* FIXME: cast away const */ + } else if (nut_foreground_passthrough == 1) { + argv[arg++] = (char *)"-F"; /* FIXME: cast away const */ + } else { + if (nut_debug_level_passthrough > 0 + && nut_debug_level > 0 + ) { + upsdebugx(1, "WARNING: Requested a debugging level " + "but not explicitly a backgrounding mode - " + "driver may never try to fork away"); + } + } + argv[arg++] = (char *)"-a"; /* FIXME: cast away const */ argv[arg++] = ups->upsname; @@ -528,6 +546,8 @@ static void help(const char *progname) printf(" -u drivers started will switch from root to \n"); printf(" -D raise debugging level\n"); printf(" -d pass debugging level from upsdrvctl to driver\n"); + printf(" -F driver stays foregrounded even if no debugging is enabled\n"); + printf(" -B driver(s) stay backgrounded even if debugging is bumped\n"); printf(" start start all UPS drivers in ups.conf\n"); printf(" start only start driver for UPS \n"); printf(" stop stop all UPS drivers in ups.conf\n"); @@ -608,6 +628,21 @@ static void send_all_drivers(void (*command)(const ups_t *)) if (command != &shutdown_driver) { ups = upstable; + /* Only warn when relevant - got more than one device to start */ + if (command == &start_driver + && ups->next + && ( (nut_foreground_passthrough == 1) + || (nut_foreground_passthrough != 0 + && nut_debug_level > 0 + && nut_debug_level_passthrough > 0) + ) + ) { + upslogx(LOG_WARNING, + "Starting \"all\" drivers but requested the " + "foreground mode (or debug without backgrounding)! " + "This request may never loop past the first driver!"); + } + while (ups) { command(ups); @@ -617,6 +652,7 @@ static void send_all_drivers(void (*command)(const ups_t *)) return; } + /* Orderly processing of shutdowns */ for (i = 0; i <= maxsdorder; i++) { ups = upstable; @@ -659,7 +695,7 @@ int main(int argc, char **argv) UPS_VERSION); prog = argv[0]; - while ((i = getopt(argc, argv, "+htu:r:DdV")) != -1) { + while ((i = getopt(argc, argv, "+htu:r:DdFBV")) != -1) { switch(i) { case 'r': pt_root = optarg; @@ -684,6 +720,14 @@ int main(int argc, char **argv) nut_debug_level_passthrough = 1; break; + case 'F': + nut_foreground_passthrough = 1; + break; + + case 'B': + nut_foreground_passthrough = 0; + break; + case 'h': default: help(prog); @@ -713,7 +757,7 @@ int main(int argc, char **argv) "starts and you need to copy and paste that line and append the debug flags to that\n" "line (less the 'exec:' prefix).\n\n" "Alternately, provide an additional '-d' (lower-case) parameter to 'upsdrvctl' to\n" - "pass its current debug level to the launched driver.\n"); + "pass its current debug level to the launched driver, and '-B' keeps it backgrounded.\n"); } if (!strcmp(argv[0], "start")) From ad18056d7746fe5789e86ccaa0fc83332c9fab14 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 13:34:35 +0100 Subject: [PATCH 0341/1232] configure.ac: drop double-quotes from NUT_REPORT*() args [#1708] --- configure.ac | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 110882eaaf..c7e1c9047a 100644 --- a/configure.ac +++ b/configure.ac @@ -1812,13 +1812,13 @@ AS_IF([test "${nut_with_nut_monitor}" != no -o "${nut_with_pynut}" != no], [ NUT_REPORT([use specific Python3 interpreter], [${PYTHON3}]) NUT_REPORT_PATH_INTEGRATIONS([Default Python interpreter site-packages], - ["${PYTHON_SITE_PACKAGES}"]) + [${PYTHON_SITE_PACKAGES}]) NUT_REPORT_PATH_INTEGRATIONS([Specific Python2 interpreter site-packages], - ["${PYTHON2_SITE_PACKAGES}"]) + [${PYTHON2_SITE_PACKAGES}]) NUT_REPORT_PATH_INTEGRATIONS([Specific Python3 interpreter site-packages], - ["${PYTHON3_SITE_PACKAGES}"]) + [${PYTHON3_SITE_PACKAGES}]) dnl # Python site-packages installation path for specific Python3 interpreter ]) @@ -2645,7 +2645,7 @@ if test "${systemdsystemunitdir}" = "auto" ; then systemdsystemunitdir=""; fi if test -n "${systemdsystemunitdir}"; then have_systemd="yes" AC_MSG_RESULT(using ${systemdsystemunitdir}) - NUT_REPORT_PATH_INTEGRATIONS([Service units for systemd], ["${systemdsystemunitdir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Service units for systemd], [${systemdsystemunitdir}]) else have_systemd="no" AC_MSG_RESULT(no) @@ -2688,7 +2688,7 @@ fi if test "${systemdshutdowndir}" = "auto" ; then systemdshutdowndir=""; fi if test -n "${systemdshutdowndir}"; then AC_MSG_RESULT(using ${systemdshutdowndir}) - NUT_REPORT_PATH_INTEGRATIONS([Shutdown hooks for systemd], ["${systemdshutdowndir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Shutdown hooks for systemd], [${systemdshutdowndir}]) else AC_MSG_RESULT(no) fi @@ -2721,7 +2721,7 @@ esac if test "${systemdtmpfilesdir}" = "auto" ; then systemdtmpfilesdir=""; fi if test -n "${systemdtmpfilesdir}"; then AC_MSG_RESULT(using ${systemdtmpfilesdir}) - NUT_REPORT_PATH_INTEGRATIONS([Systemd-tmpfiles configs], ["${systemdtmpfilesdir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Systemd-tmpfiles configs], [${systemdtmpfilesdir}]) else AC_MSG_RESULT(no) fi @@ -2974,7 +2974,7 @@ AC_ARG_WITH(augeas-lenses-dir, ], []) if test -n "${auglensdir}"; then AC_MSG_RESULT(using ${auglensdir}) - NUT_REPORT_PATH_INTEGRATIONS([Augeas lenses directory], ["${auglensdir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Augeas lenses directory], [${auglensdir}]) else AC_MSG_RESULT(no) fi @@ -3013,7 +3013,7 @@ AC_ARG_WITH(hotplug-dir, ], []) if test -n "${hotplugdir}"; then AC_MSG_RESULT(using ${hotplugdir}) - NUT_REPORT_PATH_INTEGRATIONS([Hotplug rules directory], ["${hotplugdir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Hotplug rules directory], [${hotplugdir}]) else AC_MSG_RESULT(no) fi @@ -3050,7 +3050,7 @@ AC_ARG_WITH(udev-dir, ], []) if test -n "${udevdir}"; then AC_MSG_RESULT(using ${udevdir}) - NUT_REPORT_PATH_INTEGRATIONS([Udev rules directory], ["${udevdir}"]) + NUT_REPORT_PATH_INTEGRATIONS([Udev rules directory], [${udevdir}]) else AC_MSG_RESULT(no) fi @@ -3089,7 +3089,7 @@ AC_ARG_WITH(devd-dir, ], []) if test -n "${devddir}"; then AC_MSG_RESULT(using ${devddir}) - NUT_REPORT_PATH_INTEGRATIONS([FreeBSD devd rules directory], ["${devddir}"]) + NUT_REPORT_PATH_INTEGRATIONS([FreeBSD devd rules directory], [${devddir}]) else AC_MSG_RESULT(no) fi From 828f373790af00b409ed82cfeac90e4e3cf38223 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 15:10:34 +0100 Subject: [PATCH 0342/1232] Introduce a basic .editorconfig file [#894] --- .editorconfig | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..66371823cc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,30 @@ +# EditorConfig is awesome: https://EditorConfig.org +# https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties + +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +max_line_length = 80 + +indent_style = tab +tab_width = 4 +#indent_style = space +#indent_size = 4 + +# Platform-dependent, except for certain interpreters +# whose sources must use LF, see .gitattributes +###end_of_line = lf + +[*.{bat,cmd,ps1}] +end_of_line = crlf + +[*.{sh,m4,ac,am,hwdb,service,target,path}{,.in}] +end_of_line = lf + +[*.{txt,conf,sample}{,.in}] +max_line_length = 76 From bdce51e425c7d0df7c0871fdde9f133b3538c6e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 15:23:52 +0100 Subject: [PATCH 0343/1232] Elaborate on .editorconfig [#894] --- .editorconfig | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 66371823cc..e52b2329dd 100644 --- a/.editorconfig +++ b/.editorconfig @@ -23,8 +23,32 @@ tab_width = 4 [*.{bat,cmd,ps1}] end_of_line = crlf -[*.{sh,m4,ac,am,hwdb,service,target,path}{,.in}] +[*.{sh,am,hwdb,service,target,path}{,.in}] end_of_line = lf +line_comment = # -[*.{txt,conf,sample}{,.in}] +[*.{m4,ac}{,.in}] +end_of_line = lf +line_comment = dnl + +[*.{conf,sample}{,.in}] +max_line_length = 76 +line_comment = # + +[*.txt{,.in}] max_line_length = 76 +# Assumes asciidoc comments: +block_comment_start = //////// +block_comment_end = //////// + +[*.{c,h,cpp}{,.in}] +spaces_around_operators = true +spaces_around_brackets = none + +# Plus one TAB: +continuation_indent_size = 1 + +indent_brace_style = K&R + +block_comment_start = /* +block_comment_end = */ From 779a7f3da8bc9735b1827eb7cb406be943288da7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 15:33:54 +0100 Subject: [PATCH 0344/1232] Elaborate on .editorconfig some more [#894] --- .editorconfig | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index e52b2329dd..eaedbf5277 100644 --- a/.editorconfig +++ b/.editorconfig @@ -23,10 +23,22 @@ tab_width = 4 [*.{bat,cmd,ps1}] end_of_line = crlf -[*.{sh,am,hwdb,service,target,path}{,.in}] +[*.{am,hwdb,service,target,path}{,.in}] end_of_line = lf line_comment = # +[*.sh{,.in}] +end_of_line = lf +line_comment = # + +# Borrowed from https://github.com/armbian/build/blob/master/.editorconfig +shell_variant = bash +binary_next_line = false +switch_case_indent = true +space_redirects = true +keep_padding = false +function_next_line = false + [*.{m4,ac}{,.in}] end_of_line = lf line_comment = dnl @@ -37,10 +49,21 @@ line_comment = # [*.txt{,.in}] max_line_length = 76 +indent_style = space +indent_size = 4 + # Assumes asciidoc comments: block_comment_start = //////// block_comment_end = //////// +[*.{yaml,yml,json}{,.in}] +indent_style = space +indent_size = 4 + +################################################################ +# Primary concern: C/C++ style +# See also docs/developers.txt => Code Style chapter + [*.{c,h,cpp}{,.in}] spaces_around_operators = true spaces_around_brackets = none From 4176bce2ad64e0850de69c8081b1518387539e5a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 15:41:40 +0100 Subject: [PATCH 0345/1232] docs/developers.txt: mention editorconfig [#894] --- docs/developers.txt | 7 +++++++ docs/nut.dict | 2 ++ 2 files changed, 9 insertions(+) diff --git a/docs/developers.txt b/docs/developers.txt index e2b3267a3c..fde3935a39 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -571,6 +571,13 @@ To display in a rough example: Miscellaneous coding style tools -------------------------------- +NUT codebase includes an `.editorconfig` file which should be supported +by most of the IDEs and text editors nowadays. Many support this format +specification (at least partially) out of the box, possibly with some +configuration toggle in the GUI. Others may need a plugin, see more at +https://editorconfig.org/#pre-installed page. There are also command-line +tools to verify and/or enforce compliance of source files to configuration. + You can go a long way towards converting your source code to the NUT coding style by piping it through the following command: diff --git a/docs/nut.dict b/docs/nut.dict index c7f948b31d..97204f47ce 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -471,6 +471,7 @@ IC ID's IDE IDEN +IDEs IDentifiers IFBETWEEN IFF @@ -1811,6 +1812,7 @@ ec echoback eco edb +editorconfig edl ef egrep From 69ee543d066303a914fc0774e7e41cbec3109f3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 16:07:45 +0100 Subject: [PATCH 0346/1232] .editorconfig: try to neuter additional IntelliJ IDEA formatter [#894] --- .editorconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.editorconfig b/.editorconfig index eaedbf5277..5552db6ae6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,6 +20,8 @@ tab_width = 4 # whose sources must use LF, see .gitattributes ###end_of_line = lf +ij_formatter_enabled = false + [*.{bat,cmd,ps1}] end_of_line = crlf From 9b67e7cfe3e74956bb43276f2683bdd102d7bccf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 16:12:27 +0100 Subject: [PATCH 0347/1232] .editorconfig: exempt itself from trailing whitespace (possibly needed for block-comment definitions) [#894] --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 5552db6ae6..94d993fbab 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,6 +22,9 @@ tab_width = 4 ij_formatter_enabled = false +[.editorconfig] +trim_trailing_whitespace = false + [*.{bat,cmd,ps1}] end_of_line = crlf From 147fcc1dd35a994811611e4a357bda2577bf9897 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 16:59:37 +0100 Subject: [PATCH 0348/1232] docs/man/nut_usb_addvars.txt: update comment for nut-scanner [#1790] --- docs/man/nut_usb_addvars.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 0ad8547fa2..de023ce1d5 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -7,6 +7,8 @@ Keep in sync with nut_usb_addvars() method provided by * drivers/libusb0.c * drivers/libusb1.c * drivers/usb-common.h + +and matching code in tools/nut-scanner/scan_usb.c //////// *port =* 'string':: From d2a482eda2988a1c04a99c6d060529e4d32313b3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 17:01:52 +0100 Subject: [PATCH 0349/1232] docs/man/nut_usb_addvars.txt: update comment for allow_duplicates [#1756] --- docs/man/nut_usb_addvars.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index de023ce1d5..d23e08c154 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -24,7 +24,9 @@ syntactically. It is possible to control multiple UPS units simultaneously by running several instances of this driver, provided they can be uniquely distinguished by setting some combination of the *vendor*, *product*, *vendorid*, *productid*, *serial*, -*bus* and/or *device* options detailed below. +*bus* and/or *device* options detailed +below. For devices or operating systems that do not provide sufficient +information, the *allow_duplicates* option can be of use (limited and risky!) *vendorid =* 'regex':: *productid =* 'regex':: From 687f277ce0f8442f3c4c5bae0f544aad9c7ec4c3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 16:08:31 +0100 Subject: [PATCH 0350/1232] Apply .editorconfig driven cleanup to docs [#894] --- .editorconfig | 2 +- AUTHORS | 9 +- INSTALL.nut | 61 ++--- NEWS | 2 +- README | 19 +- TODO | 2 +- UPGRADING | 4 +- docs/.editorconfig | 7 + docs/acknowledgements.txt | 12 +- docs/cables/apc.txt | 1 - docs/cables/ge-imv-victron.txt | 2 +- docs/cables/mgeups.txt | 2 +- docs/cables/powerware.txt | 1 - docs/cables/repotec.txt | 1 - docs/config-prereqs.txt | 1 - docs/maintainer-guide.txt | 1 - docs/man/.editorconfig | 7 + docs/man/apcsmart.txt | 252 +++++++++++---------- docs/man/apcupsd-ups.txt | 9 +- docs/man/asem.txt | 22 +- docs/man/bcmxcp.txt | 17 +- docs/man/bcmxcp_usb.txt | 10 +- docs/man/belkinunv.txt | 28 +-- docs/man/bestfortress.txt | 4 +- docs/man/blazer-common.txt | 126 ++++++----- docs/man/blazer_usb.txt | 1 - docs/man/generic_modbus.txt | 8 +- docs/man/liebert-esp2.txt | 17 +- docs/man/macosx-ups.txt | 8 +- docs/man/nut-ipmipsu.txt | 6 +- docs/man/nut-scanner.txt | 79 +++++-- docs/man/nut_usb_addvars.txt | 24 +- docs/man/nutdrv_qx.txt | 16 +- docs/man/nutdrv_siemens_sitop.txt | 18 +- docs/man/powerman-pdu.txt | 6 +- docs/man/socomec_jbus.txt | 14 +- docs/man/tripplite_usb.txt | 35 +-- docs/man/ups.conf.txt | 31 +-- docs/man/upsclient.txt | 6 +- docs/man/upslog.txt | 4 +- docs/nut.dict | 4 +- docs/snmp-subdrivers.txt | 3 +- docs/solaris-usb.txt | 2 +- scripts/RedHat/README | 1 - scripts/Windows/DriverInstaller/README.txt | 12 +- scripts/Windows/README | 2 +- scripts/augeas/README | 8 +- scripts/devd/README | 15 +- scripts/hotplug/README | 13 +- scripts/python/README | 27 ++- scripts/systemd/README | 1 - scripts/udev/README | 14 +- scripts/ufw/README | 2 - tests/NIT/README | 1 + tools/nut-scanner/README | 8 +- 55 files changed, 555 insertions(+), 433 deletions(-) create mode 100644 docs/.editorconfig create mode 100644 docs/man/.editorconfig diff --git a/.editorconfig b/.editorconfig index 94d993fbab..1a5e585b2c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -52,7 +52,7 @@ line_comment = dnl max_line_length = 76 line_comment = # -[*.txt{,.in}] +[*.txt{,.in},AUTHORS,COPYING,INSTALL.nut,MAINTAINERS,NEWS,README,TODO,UPGRADING] max_line_length = 76 indent_style = space indent_size = 4 diff --git a/AUTHORS b/AUTHORS index 123de62b2f..5a96fa7db3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,7 +7,7 @@ # This is a blatant ripoff of the fields found in the Linux kernel's CREDITS # file. If we need more data, those fields can always be added later. # -# N = name, E = email, W = web address, D = description, P = PGP info, +# N = name, E = email, W = web address, D = description, P = PGP info, # S = snailmail address, etc. # # This file is supposed to be roughly alpha-sorted by the last name, but @@ -17,7 +17,7 @@ N: Stephen Brown E: steve@datalimbo.net W: http://www.datalimbo.net/ -D: Hacked genericups to add TrippLite Lan2.x support (Internet Office 700) +D: Hacked genericups to add TrippLite Lan2.x support (Internet Office 700) N: Bill Carlson E: wcarlson@wkks.org @@ -140,7 +140,7 @@ E: lwhite@darkfires.net N: Walt Holman E: walt_h@lorettotel.net -D: Hacked up the cpsups driver for CyberPower text protocol UPSes +D: Hacked up the cpsups driver for CyberPower text protocol UPSes N: Fabio Di Niro E: blaxwan@users.sourceforge.net @@ -177,4 +177,5 @@ D: Author of asem driver N: zakx E: zakx@zakx.de -D: Updating device support docs after unnecessarily writing a redundant driver first +D: Updating device support docs after unnecessarily writing a redundant +D: driver first diff --git a/INSTALL.nut b/INSTALL.nut index 58a0f970b5..4b99ba6a14 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -4,10 +4,10 @@ Installation instructions This chapter describes the various methods for installing Network UPS Tools. Whenever it is possible, prefer <>. -Packagers have done an excellent and hard work at improving NUT integration into -their system. On the other hand, distributions and appliances tend to package -"official releases" of projects such as NUT, and so do not deliver latest and -greatest fixes, new drivers, bugs and other features. +Packagers have done an excellent and hard work at improving NUT integration +into their operating system. On the other hand, distributions and appliances +tend to package "official releases" of projects such as NUT, and so do not +deliver latest and greatest fixes, new drivers, bugs and other features. [[Installing_source]] Installing from source @@ -38,20 +38,21 @@ you might select a sub-set of those suggestions). ================================================================================ - the paths shown below are the default values you get by just calling -configure by itself. If you have used --prefix or similar, things will be -different. Also, if you didn't install this program from source yourself, the -paths will probably have a number of differences. + configure by itself. If you have used --prefix or similar, things will be + different. Also, if you didn't install this program from source yourself, + the paths will probably have a number of differences. - by default, your system probably won't find the man pages, since they -install to /usr/local/ups/man. You can fix this by editing your MANPATH, or -just do this: + install to /usr/local/ups/man. You can fix this by editing your MANPATH, + or just do this: man -M /usr/local/ups/man -- if your favorite system offers up to date binary packages, you should always -prefer these over a source installation. Along with the known advantages of such -systems for installation, upgrade and removal, there are many integration issues -that have been addressed. +- if your favorite system offers up to date binary packages, you should + always prefer these over a source installation (unless there are known + deficiencies in the package or one is too obsolete). Along with the known + advantages of such systems for installation, upgrade and removal, there + are many integration issues that have been addressed. ================================================================================ @@ -62,8 +63,8 @@ Prepare your system System User creation ^^^^^^^^^^^^^^^^^^^^ -Create at least one system user and a group for running this software. You -might call them "ups" and "nut". The exact names aren't important as +Create at least one system user and a group for running this software. +You might call them "ups" and "nut". The exact names aren't important as long as you are consistent. The process for doing this varies from one system to the next, and @@ -240,7 +241,8 @@ the 'nut' package, and optionally the following: Configuration files are located in /etc/nut. linkman:nut.conf[5] must be edited to be able to invoke /etc/init.d/nut -NOTE: Ubuntu users can access the APT URL installation by clicking on link:apt://nut[this link]. +NOTE: Ubuntu users can access the APT URL installation by clicking +on link:apt://nut[this link]. [[Mandriva]] @@ -250,8 +252,8 @@ Mandriva NOTE: NUT is packaged and well maintained in these systems. The official Mandriva packager is part of the NUT Team. -Using your preferred method (urpmi, RPMdrake, ...), install one of the two below -packages: +Using your preferred method (urpmi, RPMdrake, ...), install one of the +two below packages: - 'nut-server' if you have a 'standalone' or 'netserver' installation, - 'nut' if you have a 'netclient' installation. @@ -287,8 +289,8 @@ Red Hat, Fedora and CentOS NOTE: NUT is packaged and well maintained in these systems. The official Red Hat packager is part of the NUT Team. -Using your preferred method (yum, Add/Remove Software, ...), install one of the -two below packages: +Using your preferred method (yum, Add/Remove Software, ...), install +one of the two below packages: - 'nut' if you have a 'standalone' or 'netserver' installation, - 'nut-client' if you have a 'netclient' installation. @@ -317,7 +319,8 @@ Port ^^^^ The port is located under +sysutils/nut+. -Use +make config+ to select configuration options, e.g. to build the optional CGI scripts. +Use +make config+ to select configuration options, e.g. to build the +optional CGI scripts. To install it, use: # make install clean @@ -325,13 +328,15 @@ To install it, use: USB UPS on FreeBSD ^^^^^^^^^^^^^^^^^^ -For USB UPS devices the NUT package/port installs devd rules in +/usr/local/etc/devd/nut-usb.conf+ to set USB device permissions. 'devd' needs to be restarted for these rules to apply: +For USB UPS devices the NUT package/port installs devd rules in ++/usr/local/etc/devd/nut-usb.conf+ to set USB device permissions. + 'devd' needs to be restarted for these rules to apply: # service devd restart -(Re-)connect the device after restarting 'devd' and check that the USB device has the proper -permissions. Check the last entries of the system message buffer. You should -find an entry like +(Re-)connect the device after restarting 'devd' and check that the USB +device has the proper permissions. Check the last entries of the system +message buffer. You should find an entry like: # dmesg | tail [...] @@ -349,7 +354,8 @@ using: # usbconfig -u 0 -a 2 dump_device_desc -where +-u+ specifies the USB bus number and +-a+ specifies the USB device index. +where +-u+ specifies the USB bus number and +-a+ specifies the USB device +index. [[Windows]] @@ -403,7 +409,8 @@ Newer Windows releases should include the Windows Installer natively. Run `NUT-Installer.msi` and follow the wizard indications. -If you plan to use an UPS which is locally connected to an USB port, you have to install +If you plan to use an UPS which is locally connected to an USB port, +you have to install link:https://sourceforge.net/projects/libusb-win32/files/[libUSB-win32] on your system. Then you must install your device via libusb's "Inf Wizard". diff --git a/NEWS b/NEWS index 17f42d52ce..93196ee8f6 100644 --- a/NEWS +++ b/NEWS @@ -2281,7 +2281,7 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1: - upssched now uses a lock file to prevent a race where two could start at the same time. The second upssched would "win", and the first one would be unreachable. This had the side-effect of not - being able to cancel timers on the first one. + being able to cancel timers on the first one. If you use upssched, you must define the LOCKFN directive when upgrading to this version, or it will not work. diff --git a/README b/README index c57dd89e97..608c52c1b2 100644 --- a/README +++ b/README @@ -11,8 +11,8 @@ It uses a layered approach to connect all of the parts. Drivers are provided for a wide assortment of equipment. They understand the specific language of each device and map it back to a compatibility layer. This means both an expensive high end UPS, a simple -"power strip" PDU, or any other power device can be handled transparently with -a uniform management interface. +"power strip" PDU, or any other power device can be handled transparently +with a uniform management interface. This information is cached by the network server `upsd`, which then answers queries from the clients. upsd contains a number of access @@ -35,8 +35,8 @@ Installing If you are installing these programs for the first time, go read the <<_installation_instructions,installation instructions>> -to find out how to do that. This document contains more information on what all -of this stuff does. +to find out how to do that. This document contains more information +on what all of this stuff does. Upgrading @@ -44,8 +44,8 @@ Upgrading When upgrading from an older version, always check the <> to see what may have -changed. Compatibility issues and other changes will be listed there to ease -the process. +changed. Compatibility issues and other changes will be listed there +to ease the process. Configuring and using @@ -59,8 +59,8 @@ Documentation ------------- This is just an overview of the software. You should read the man pages, -included example configuration files, and auxiliary documentation for the parts -that you intend to use. +included example configuration files, and auxiliary documentation for the +parts that you intend to use. Network Information @@ -180,7 +180,8 @@ If your driver has vanished, see the link:FAQ.html[FAQ] and Generic Device Drivers ~~~~~~~~~~~~~~~~~~~~~~ -NUT provides several generic drivers that support a variety of very similar models. +NUT provides several generic drivers that support a variety of very similar +models. - The `genericups` driver supports many serial models that use the same basic principle to communicate with the computer. This is known as "contact diff --git a/TODO b/TODO index 81a601f2d6..e81d278122 100644 --- a/TODO +++ b/TODO @@ -18,7 +18,7 @@ the excellent link:https://asciidoc.org/[AsciiDoc]. 2.8 ^^^ -This branch will focus on configuration and user interface improvements. +This branch will focus on configuration and user interface improvements. 3.0 ^^^ diff --git a/UPGRADING b/UPGRADING index 701d8412c4..150d1ddc1b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -3,7 +3,7 @@ Upgrading notes =============== endif::txt[] -This file lists changes that affect users who installed older versions +This file lists changes that affect users who installed older versions of this software. When upgrading from an older version, be sure to check this file to see if you need to make changes to your system. @@ -511,7 +511,7 @@ which makes it work with upsclient. has been gone for a long time, and the target was ambiguous. - The newapc driver has been renamed to apcsmart. If you previously -used newapc, make sure you delete the old binary and fix your +used newapc, make sure you delete the old binary and fix your ups.conf. Otherwise, you may run the old driver from 1.4. diff --git a/docs/.editorconfig b/docs/.editorconfig new file mode 100644 index 0000000000..66d4744a76 --- /dev/null +++ b/docs/.editorconfig @@ -0,0 +1,7 @@ +# Nested configuration file + +# The following documents with code samples have +# intentional trailing whitespace and should be +# only reformatted manually and attentively: +[{ci-farm-lxc-setup,solaris-usb}.txt] +trim_trailing_whitespace = false diff --git a/docs/acknowledgements.txt b/docs/acknowledgements.txt index 7597bb224b..77d0fd30ab 100644 --- a/docs/acknowledgements.txt +++ b/docs/acknowledgements.txt @@ -8,8 +8,8 @@ This project is the result of years of work by many individuals and companies. Many people have written or tweaked the software; the drivers, clients, server and documentation have all received valuable attention from numerous sources. -Many of them are listed within the source code, AUTHORS file, release notes, and -mailing list archives, but some prefer to be anonymous. +Many of them are listed within the source code, AUTHORS file, release notes, +and mailing list archives, but some prefer to be anonymous. This software would not be possible without their help. @@ -19,8 +19,10 @@ The NUT Team Active members ~~~~~~~~~~~~~~ -- Jim Klimov: project leader (since 2020), OpenIndiana and OmniOS packager, CI ops and infra -- Arnaud Quette: ex-project leader (from 2005 to 2020), Debian packager and jack of all trades +- Jim Klimov: project leader (since 2020), OpenIndiana and OmniOS packager, + CI dev/ops and infra +- Arnaud Quette: ex-project leader (from 2005 to 2020), Debian packager + and jack of all trades - Charles Lepple: senior lieutenant - Daniele Pezzini: senior developer - Kjell Claesson: senior developer @@ -120,7 +122,7 @@ list, and the rest of the information is available via the link:http://article.gmane.org/gmane.comp.monitoring.nut.user/8173[list archives]. -* link:https://nag.company/en[NAG], through Alexey Kazancev and Igor Ryabov, +* link:https://nag.company/en[NAG], through Alexey Kazancev and Igor Ryabov, has added support for SNR-UPS-LID-XXXX models as usb-hid UPS. * link:http://www.ablerex.com.tw/[Ablere Electronics Co., Ltd.] contributed diff --git a/docs/cables/apc.txt b/docs/cables/apc.txt index 5803779024..94d2c32daf 100644 --- a/docs/cables/apc.txt +++ b/docs/cables/apc.txt @@ -258,4 +258,3 @@ had some shielding issues from the manufacturer that could maybe cause | NOTE: Solder a wire to the metal shell for use as a FRAME-GND | | | +-----------------------------------------------------------------+ - diff --git a/docs/cables/ge-imv-victron.txt b/docs/cables/ge-imv-victron.txt index 6a8441746d..d38b83926d 100644 --- a/docs/cables/ge-imv-victron.txt +++ b/docs/cables/ge-imv-victron.txt @@ -56,4 +56,4 @@ UPS PC 9 pin connector ---------------------------------------------- GE is General Electric Company. -On July 31, 2001, the General Electric Company, acquisited IMV (Victron) company. +On July 31, 2001, the General Electric Company, acquired IMV (Victron) company. diff --git a/docs/cables/mgeups.txt b/docs/cables/mgeups.txt index ea4c4f0e62..64a5bdc7dc 100644 --- a/docs/cables/mgeups.txt +++ b/docs/cables/mgeups.txt @@ -49,4 +49,4 @@ Notes trouble communication on some Unices if cabled. However, new models (such as Ellipse, Evolution, Pulsar and Comet EXtreme, EXtreme C, ...) handle this, so you can safely cable pin 6 or - use a standard (bundled) "windows" cable (Ref 66049). \ No newline at end of file + use a standard (bundled) "windows" cable (Ref 66049). diff --git a/docs/cables/powerware.txt b/docs/cables/powerware.txt index 1db1a77a14..0b839910c2 100644 --- a/docs/cables/powerware.txt +++ b/docs/cables/powerware.txt @@ -23,4 +23,3 @@ Pin 2 <-----------> Pin 8 Pin 4 <-----------> Pin 4 Pin 5 <-----------> Pin 1 Shells Grounded Both Ends - diff --git a/docs/cables/repotec.txt b/docs/cables/repotec.txt index 3d26a70019..a7569fc0c7 100644 --- a/docs/cables/repotec.txt +++ b/docs/cables/repotec.txt @@ -23,4 +23,3 @@ PC UPS 5 (GND) -------------+-- 4 | +-- 7 - diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 21159a70ab..abb3167318 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -1265,4 +1265,3 @@ problematic on that platform) may be needed in other directories, such as ------ :; ( cd "$DESTDIR/mingw64/bin/" && ln *.dll ../sbin && ln *.dll ../cgi-bin ) ------ - diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index 3c16955a67..62269bbe94 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -88,5 +88,4 @@ SANDBOX (to be completed and pushed) * update nut/ and ddl/ submodules in nut-website/ (this should update the website's version as well) * add download hashes for tarball - ////////////////////////////////////////////////////////////////////////////// diff --git a/docs/man/.editorconfig b/docs/man/.editorconfig new file mode 100644 index 0000000000..2c3b51973d --- /dev/null +++ b/docs/man/.editorconfig @@ -0,0 +1,7 @@ +# Nested configuration file + +# The following documents with code samples have +# intentional trailing whitespace and should be +# only reformatted manually and attentively: +[{nut.conf,upsmon.conf}.txt] +trim_trailing_whitespace = false diff --git a/docs/man/apcsmart.txt b/docs/man/apcsmart.txt index 503ff57701..9a314519e0 100644 --- a/docs/man/apcsmart.txt +++ b/docs/man/apcsmart.txt @@ -21,20 +21,22 @@ linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -The apcsmart driver should recognize (or at the very least, work with) the -majority of Smart-UPS models - which includes Smart-UPS, Matrix-UPS and Back-UPS -lineups, among few other ones. +The apcsmart driver should recognize (or at the very least, work with) +the majority of Smart-UPS models -- which includes Smart-UPS, Matrix-UPS +and Back-UPS lineups, among few other ones. -Currently, we can roughly divide APC hardware into four groups (note that the -division isn't strict by any means, and the borders between those are pretty fuzzy): +Currently, we can roughly divide APC hardware into four groups (note +that the division isn't strict by any means, and the borders between +those are pretty fuzzy): [very] "old" models:: - These models usually have old APC logo, white color and _no_ programmable - EEPROM; you won't find them listed anywhere on APC's site either. The support - for those will be usually based on driver's compatibility tables, or if the - model (firmware) is not listed in those - the driver will try to follow the very - basic subset of features, while still trying to remain useful. Despite - "smart" tagname, they often tend to behave in pretty dumb way (see the + These models usually have old APC logo, white color and _no_ + programmable EEPROM; you won't find them listed anywhere on APC's + site either. The support for those will be usually based on driver's + compatibility tables, or if the model (firmware) is not listed in + those -- the driver will try to follow the very basic subset of + features, while still trying to remain useful. Despite "smart" + tagname, they often tend to behave in pretty dumb way (see the section below about shutdown behaviour). + -- @@ -44,27 +46,33 @@ division isn't strict by any means, and the borders between those are pretty fuz -- "new" models:: - These models usually come from late 1990s / pre-2009 times. They are often - referred as "3rd. gen". For the most part, they have programmable EEPROM, - report supported commands and capabilities, and should work just fine with the - apcsmart driver. + These models usually come from late 1990s / pre-2009 times. + They are often referred to as "3rd. gen". For the most part, they + have programmable EEPROM, report supported commands and capabilities, + and should work just fine with the apcsmart driver. "microlink" models:: - WARNING: these are not _natively_ supported by *apcsmart* (or *apcupsd*, - for that matter, if you're wondering). Around 2007, APC (now APC Schneider) - decided to go back to its proprietary roots, and all the new models (SMT, - SMX, SURTD) use completely different protocol and cables. If you purchased - a new APC UPS - that uses cable with RJ45 on the one end, and DB-9 on the - other - then you have such model. Your only option to support it through - *NUT* is to purchase a "legacy communications card" - part #AP9620 (google - 'AP9620' for more details). Or if that's not an option, rely on official - software. + WARNING: these are not _natively_ supported by *apcsmart* (or as of + this writing by *apcupsd*, for that matter, if you're wondering). + Around 2007, APC (now APC Schneider) decided to go back to its + proprietary roots, and all the new models (SMT, SMX, SURTD) use + completely different protocol and cables. If you purchased + a new APC UPS -- that uses cable with RJ45 on the one end, and DB-9 + on the other -- then you have such model. Your only option to support + it through *NUT* is to purchase a "legacy communications card" -- + part #AP9620 (google 'AP9620' for more details). Or if that's not + an option, rely on official software. + + + UPDATE: later releases of *apcupsd* claimed support for new APC + protocols, so it is worth checking if *apcupsd* software would + work with your device, and *apcupsd-ups* NUT driver would handle + it as part of NUT-managed ecosystem. Microsol models:: - Several Microsol serial models sold in Brazil have been rebranded as APC - Back-UPS, and the model numbers tend to start with "BZ". If you have one - of these "Nobreaks", they will not work with the *apcsmart* driver - please - see the linkman:solis[8] driver instead. + Several Microsol serial models sold in Brazil have been rebranded + as APC Back-UPS, and the model numbers tend to start with "BZ". + If you have one of these "Nobreaks", they will not work with the + *apcsmart* driver -- please see the linkman:solis[8] driver instead. + -- .Example models: @@ -72,9 +80,9 @@ Microsol models:: * Back-UPS BZ2200BI-BR -- -Another thing to remember is that Smart protocol is not USB protocol. If you -have UPS with both USB and serial ports, then depending on how you connect it, -you will need either apcsmart or usbhid-ups driver. +Another thing to remember is that Smart protocol is not USB protocol. +If you have UPS with both USB and serial ports, then depending on how +you connect it, you will need either apcsmart or usbhid-ups driver. CABLING ------- @@ -105,10 +113,11 @@ Alternatively, you can also provide it on the command line using: TTY MODES --------- -By default the driver works in canonical mode, but it proved to be a problem in -Windows systems. Furthermore there's a possibility of some obscure serial cards -or serial-USB converters that could cause problems as well. You can use -'ttymode=' option to force non-canonical discipline in linkman:ups.conf[5]: +By default the driver works in canonical mode, but it proved to be a +problem in Windows systems. Furthermore there's a possibility of some +obscure serial cards or serial-USB converters that could cause problems +as well. You can use 'ttymode=' option to force non-canonical discipline +in linkman:ups.conf[5]: *ttymode*=raw @@ -121,8 +130,8 @@ NOTE: Any other value will make the driver work in the canonical mode. EXPLANATION OF SHUTDOWN METHODS SUPPORTED BY APC UPSES ------------------------------------------------------ -APC hardware supports a lot of shutdown methods, that themselves can differ in -behaviour quite a bit, depending on the model. +APC hardware supports a lot of shutdown methods, that themselves can +differ in behaviour quite a bit, depending on the model. *S* (soft hibernate):: This is most basic command present in probably all APC models. It will @@ -131,26 +140,27 @@ behaviour quite a bit, depending on the model. + -- "old" models: :: - The behaviour here is unfortunately pretty primitive - when the power - returns, the UPS just wakes up. No grace periods, no min. battery - charge condition, etc. This is probably not what you want. + The behaviour here is unfortunately pretty primitive - + when the power returns, the UPS just wakes up. No grace periods, + no min. battery charge condition, etc. This is probably not what + you want. "new" models: :: - The behaviour here is as expected - the power is cut off after the + The behaviour here is as expected -- the power is cut off after the EEPROM defined grace period. The UPS will wake up when the power - returns, after the EEPROM defined delay AND if the EEPROM defined min. - battery charge level is met. The delay is counted from the power's - return. + returns, after the EEPROM defined delay AND if the EEPROM defined + min. battery charge level is met. The delay is counted from the + power's return. -- + *CS* (aka "force OB hack"):: This is a trick to make UPS power down even if it's running on mains. - Immediately before issuing *S*, "simulate power failure" is issued. The - remaining behaviour is as in *S* case. + Immediately before issuing *S*, "simulate power failure" is issued. + The remaining behaviour is as in *S* case. + -There's a delay between "simulate power failure" and *S* - by default set to -3.5s. You can control it through *cshdelay* option (allowed values are from 0 -to 9.9). +There's a delay between "simulate power failure" and *S* -- by default +set to 3.5s. You can control it through *cshdelay* option (allowed +values are from 0 to 9.9). + The name came from APC CS models, where such trick was used to power down UPSes in consistent fashion using only *S*. It's better to use *@nnn* @@ -158,17 +168,20 @@ command if your UPS supports it (and is not too old, see below). *@nnn* (hard hibernate):: This is basic command used to hibernate UPS regardless if it's - running on batteries or on mains. The option takes 3 digits argument which - can be used to specify additional wake-up delay (in 6 minute units). + running on batteries or on mains. The option takes 3 digits argument + which can be used to specify additional wake-up delay (in 6 minute + units). + -- "old" models: :: - The behaviour is - unfortunately - similarly primitive to *S*. The UPS - unconditionally wakes up after $$nnn*6$$ minutes - *it doesn't care if the - power returned !* If nnn = 000, then UPS will do precisely nothing. On - those models you're better specifying nnn > 0, if you can estimate - the kind of power problems that might be happening in your environment. - Another thing to consider with "old" models - you might lose the + The behaviour is -- unfortunately -- similarly primitive to *S*. + The UPS unconditionally wakes up after $$nnn*6$$ minutes: + *it doesn't care if the power returned !* + If nnn = 000, then UPS will do precisely nothing. + On those models you're better specifying nnn > 0, if you can + estimate the kind of power problems that might be happening + in your environment. + Another thing to consider with "old" models -- you might lose the connection with the UPS, until it wakes up (with *S*, the serial connection is kept alive). @@ -176,8 +189,8 @@ command if your UPS supports it (and is not too old, see below). All the usual variables defined in EEPROM are respected (see *S*). Additionally, if nnn > 0, the $$nnn*6$$ minutes are added to EEPROM defined delay. UPS will not power up if it's running on batteries, - contrary to what "old" models used to do - the combined delay is counted - from the moment of power return. + contrary to what "old" models used to do -- the combined delay is + counted from the moment of power return. -- + Supposedly there exist models that take 2 digits instead of 3. Just in case, @@ -185,11 +198,11 @@ NUT also supports such variation. You have to provide exactly 2 digits to trigger it (*awd* option, or argument to one of the supported instant commands). *K* (delayed poweroff):: - This is permanent poweroff - the UPS will not wake up automatically. On - newer units, it will respect applicable EEPROM variables. + This is permanent poweroff -- the UPS will not wake up automatically. + On newer units, it will respect applicable EEPROM variables. *Z* (instant poweroff):: - This is also permanent poweroff - the UPS will not wake up automatically. + This is also permanent poweroff -- the UPS will not wake up automatically. The poweroff is executed immediately. SHUTDOWN CONTROL BY NUT @@ -202,35 +215,36 @@ There are three options used to control the shutdown behaviour. details. *advorder*=no|[0-4]+:: - This option takes string of digits as an argument. Methods listed are tried - in turn until one of them succeeds. Note that the meaning of digits is - different from *sdtype*. See below for details. + This option takes string of digits as an argument. Methods listed + are tried in turn until one of them succeeds. Note that the meaning + of digits is different from *sdtype*. See below for details. *awd*=[0-9]{1,3}:: - This option lets you specify additional wake-up delay used by *@*. If you - provide exactly 2 digits, the driver will try 2 digits variation (see - previous section for more info). Otherwise standard 3 digits variation is - used. *Note: the time unit is 6 minutes !* + This option lets you specify additional wake-up delay used by *@*. + If you provide exactly 2 digits, the driver will try 2 digits + variation (see previous section for more info). + Otherwise standard 3 digits variation is used. + *Note: the time unit is 6 minutes !* -Keep in mind that *sdtype* and *advorder* are mutually exclusive. If *advorder* -is provided, *sdtype* is ignored. If *advorder* is set to 'no', *sdtype* is -used instead. +Keep in mind that *sdtype* and *advorder* are mutually exclusive. +If *advorder* is provided, *sdtype* is ignored. If *advorder* is +set to 'no', *sdtype* is used instead. -If nothing is provided, *NUT* will assume *sdtype*=0 - which is generally fine -for anything not too ancient or not too quirky. +If nothing is provided, *NUT* will assume *sdtype*=0 -- which is +generally fine for anything not too ancient or not too quirky. SDTYPE ~~~~~~ -The values permitted are from 0 to 5. Only one can be specified. Anything else -will cause apcsmart to exit. +The values permitted are from 0 to 5. Only one can be specified. +Anything else will cause apcsmart to exit. 0:: -issue soft hibernate (*S*) if the UPS is running on batteries, otherwise issue -hard hibernate (*@*) +issue soft hibernate (*S*) if the UPS is running on batteries, +otherwise issue hard hibernate (*@*) 1:: -issue soft hibernate (*S*) (if on batteries), and if it fails (or on mains) - -try hard hibernate (*@*) +issue soft hibernate (*S*) (if on batteries), and if it fails +(or on mains) -- try hard hibernate (*@*) 2:: issue instant poweroff (*Z*) 3:: @@ -245,7 +259,7 @@ NOTE: Hard hibernate's additional wake-up delay can be provided by *awd*. ADVORDER ~~~~~~~~ -The argument is either a word 'no', or a string of 1 - 5 digits in [0 - 4] +The argument is either a word 'no', or a string of 1..5 digits in [0..4] range. Each digit maps to the one of shutdown methods supported by APC UPSes. Methods listed in this way are tried in order, until one of them succeeds. @@ -265,10 +279,10 @@ NOTE: Hard hibernate's additional wake-up delay can be provided by *awd*. IGNORING LB STATE ----------------- -APC units - even if they report LB mode - will not go into shutdown +APC units -- even if they report LB mode -- will not go into shutdown automatically. This gives us even more control with reference to "when to -actually shutdown PSU". Since version 2.6.2, NUT supports *ignorelb* option in -driver's section of linkman:ups.conf[5]. When such option is in effect, +actually shutdown PSU". Since version 2.6.2, NUT supports *ignorelb* option +in driver's section of linkman:ups.conf[5]. When such option is in effect, the core driver will ignore LB state as reported by specific driver and start shutdown basing the decision _only_ on two conditions: @@ -278,21 +292,22 @@ battery.charge < battery.charge.low battery.runtime < battery.runtime.low -Of course - if any of the variables are not available, the appropriate condition -is not checked. If you want to explicitly disable one of the conditions, simply -override the right hand variable causing the condition to always evaluate to -false (you can even provide negative numbers). +Of course -- if any of the variables are not available, the appropriate +condition is not checked. If you want to explicitly disable one of the +conditions, simply override the right hand variable causing the condition +to always evaluate to false (you can even provide negative numbers). -APC UPSes don't have battery.charge.low - you will have to define it if you want -to use such condition (prefix the variable with `override.` or `default.`). +APC UPSes don't have battery.charge.low -- you will have to define it +if you want to use such condition (prefix the variable with `override.` +or `default.`). -"New" units have battery.runtime.low, but depending on battery quality, firmware -version, calibration and UPS load - this variable can be underestimated quite a bit - -especially right after going into OB state. This in turn can cause LB to be -asserted, which under normal conditions will cause *NUT* to initiate the -shutdown. You might want to disable this condition entirely, when relying on -*ignorelb* option (this was actually the main motivation behind introduction of -such feature). +"New" units have battery.runtime.low, but depending on battery quality, +firmware version, calibration and UPS load -- this variable can be +underestimated quite a bit -- especially right after going into OB state. +This in turn can cause LB to be asserted, which under normal conditions +will cause *NUT* to initiate the shutdown. You might want to disable +this condition entirely, when relying on *ignorelb* option (this was +actually the main motivation behind introduction of such feature). Simple example: ---- @@ -302,17 +317,17 @@ Simple example: override.battery.runtime.low = -1 ---- -This would cause apcsmart to go into shutdown _only_ if detected battery charge -< 15%. Runtime condition is always false in this example. +This would cause apcsmart to go into shutdown _only_ if detected +battery charge < 15%. Runtime condition is always false in this example. -You could ask - why bother ? Well, the reason is already hinted above. APC units -can be very picky about the batteries, and their firmware can underestimate the -remaining runtime (especially right after going into OB state). *ignorelb* -option and *$$override.*$$* let you remain in control of the UPS, not UPS in control -of you. +You could ask -- why bother ? Well, the reason is already hinted above. +APC units can be very picky about the batteries, and their firmware can +underestimate the remaining runtime (especially right after going into +OB state). *ignorelb* option and *$$override.*$$* let you remain in +control of the UPS, not UPS in control of you. -Furthermore, this allows to specify conditions similarly to how it's done in -apcupsd daemon, so it should be welcome by people used to that software. +Furthermore, this allows to specify conditions similarly to how it's done +in apcupsd daemon, so it should be welcome by people used to that software. SUPPORTED INSTANT COMMANDS @@ -322,20 +337,24 @@ The apcsmart driver exposes following instant commands: shutdown.return:: executes soft hibernate + shutdown.return cs:: executes "force OB hack" + shutdown.return at::: -executes "hard hibernate" with $$*6$$ minutes additional wake-up delay ( format -is the same as of *awd* option) +executes "hard hibernate" with $$*6$$ minutes additional wake-up +delay ( format is the same as of *awd* option) + shutdown.stayoff:: executes "delayed poweroff" + load.off:: executes "instant poweroff" -All the above commands must be issued 2nd time to have any effect (no less than 3 -seconds, and no more than 15 seconds after the initial call). Those commands are -mostly useful for manual testing, when your machine is not powered by the UPS -you're testing. +All the above commands must be issued 2nd time to have any effect +(no less than 3 seconds, and no more than 15 seconds after the initial +call). Those commands are mostly useful for manual testing, when your +machine is not powered by the UPS you're testing. Other supported commands: @@ -352,10 +371,11 @@ Other supported commands: PREVIOUS DRIVER VERSION ----------------------- -Previous driver is still available as *apcsmart-old*, should there be any need to -use earlier version (bugs, incompatibilities with new functionality, etc.). In -due time, *apcsmart-old* will be phased out completely, but this won't happen until -the new version gets solid exposure with no pending issues. +Previous driver is still available as *apcsmart-old*, should there be +any need to use earlier version (bugs, incompatibilities with new +functionality, etc.). In due time, *apcsmart-old* will be phased out +completely, but this won't happen until the new version gets solid +exposure with no pending issues. BUGS ---- diff --git a/docs/man/apcupsd-ups.txt b/docs/man/apcupsd-ups.txt index 1017bd2f84..74f2b164c5 100644 --- a/docs/man/apcupsd-ups.txt +++ b/docs/man/apcupsd-ups.txt @@ -91,10 +91,11 @@ if you notice a mismatch in units). LIMITATIONS ----------- -Access to *apcupsd* is strictly read only: no commands can be issued. This -stems from the design of *apcupsd*, where the settings are changed in -*apctest*. In order to run *apctest*, *apcupsd* must be stopped (and *apcupsd* -exposes the UPS to the network). +Access to *apcupsd* is strictly read only: no commands can be issued. +This stems from the design of *apcupsd*, where the settings are changed +in *apctest*. In order to run *apctest*, *apcupsd* must be stopped +(and it is *apcupsd* exposes the UPS to the network and to this NUT +driver as its client). AUTHOR ------ diff --git a/docs/man/asem.txt b/docs/man/asem.txt index b45cf11a36..838ddafc70 100644 --- a/docs/man/asem.txt +++ b/docs/man/asem.txt @@ -16,14 +16,14 @@ linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -The *asem* driver supports the UPS in ASEM PB1300 embedded PCs. Likely other -I2C devices from the same manufacturer will work too, since this is a "custom" -charger. +The *asem* driver supports the UPS in ASEM PB1300 embedded PCs. +Likely other I2C devices from the same manufacturer will work too, +since this is a "custom" charger. Seems that there are two versions of the charger. Older one is based on Max1667, newer one is a custom solution. Both are on I2C address 0x09. -To be compatible with both versions, the driver just reads bit 15 of address -0x13 which yields online/on battery status. +To be compatible with both versions, the driver just reads bit 15 of +address 0x13 which yields online/on battery status. Battery monitor is a BQ2060 at address 0x0B. EXTRA ARGUMENTS @@ -48,10 +48,10 @@ INSTALLATION This driver is specific to the Linux I2C API, and requires the lm_sensors libi2c-dev or its equivalent to compile. -Beware that the SystemIO memory used by the I2C controller is reserved by ACPI. -If only a native I2C driver (e.g. i2c_i801, as of 3.5.X Linux kernels) is -available, then you'll need to relax the ACPI resources check. For example, you -can boot with the `acpi_enforce_resources=lax` option. +Beware that the SystemIO memory used by the I2C controller is reserved +by ACPI. If only a native I2C driver (e.g. i2c_i801, as of 3.5.X Linux +kernels) is available, then you'll need to relax the ACPI resources check. +For example, you can boot with the `acpi_enforce_resources=lax` option. ////////////////////////////////////////// Optional: use DIAGNOSTICS to describe troubleshooting techniques that are @@ -65,8 +65,8 @@ DIAGNOSTICS KNOWN ISSUES AND BUGS --------------------- -The driver shutdown function is not implemented, so other arrangements must be -made to turn off the UPS. +The driver shutdown function is not implemented, so other arrangements +must be made to turn off the UPS. AUTHOR ------ diff --git a/docs/man/bcmxcp.txt b/docs/man/bcmxcp.txt index 037e1b0f48..303d404132 100644 --- a/docs/man/bcmxcp.txt +++ b/docs/man/bcmxcp.txt @@ -16,10 +16,10 @@ linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -This driver should recognize all serial BCM/XCP-compatible UPSes. It has -been developed and tested on Powerware PW5115 and PW9120 hardware. If your UPS -has a USB connection, you may also consult the linkman:bcmxcp_usb[8] driver -documentation. +This driver should recognize all serial BCM/XCP-compatible UPSes. +It has been developed and tested on Powerware PW5115 and PW9120 hardware. +If your UPS has a USB connection, you may also consult the +linkman:bcmxcp_usb[8] driver documentation. EXTRA ARGUMENTS --------------- @@ -32,10 +32,11 @@ The number of seconds that the UPS should wait between receiving the shutdown command (`upsdrvctl shutdown`) and actually shutting off. *baud_rate=*'rate':: -Communication speed for the UPS. If this is set to 9600, it tries to connect -to the UPS at 9600bps. If it fails to communicate, it will go into baud-hunting. -It starts at 1200 and goes up to 19200. If it succeeds, it tell you the speed it -connected with. If not included in the config, it defaults to baud-hunting. +Communication speed for the UPS. If this is set to 9600, it tries to +connect to the UPS at 9600bps. If it fails to communicate, it will go +into baud-hunting. It starts at 1200 and goes up to 19200. +If it succeeds, it tell you the speed it connected with. +If not included in the config, it defaults to baud-hunting. DEFAULT VALUES FOR THE EXTRA ARGUMENTS -------------------------------------- diff --git a/docs/man/bcmxcp_usb.txt b/docs/man/bcmxcp_usb.txt index 32f8261c86..4906be1c30 100644 --- a/docs/man/bcmxcp_usb.txt +++ b/docs/man/bcmxcp_usb.txt @@ -4,7 +4,8 @@ BCMXCP_USB(8) NAME ---- -bcmxcp_usb - Experimental driver for UPSes supporting the BCM/XCP protocol over USB +bcmxcp_usb - Experimental driver for UPSes supporting the BCM/XCP protocol +over USB NOTE ---- @@ -12,14 +13,15 @@ NOTE This man page only documents the hardware-specific features of the bcmxcp_usb driver. For information about the core driver, see linkman:nutupsdrv[8]. -This driver is a variant of the serial driver bcmxcp and uses the same core code. +This driver is a variant of the serial driver bcmxcp and uses the same +core code. SUPPORTED HARDWARE ------------------ This driver should recognize all BCM/XCP-compatible UPSes that are connected -via USB. It has been developed and tested on Powerware PW3501 hardware. It also has -been tested on PW5110 hardware. +via USB. It has been developed and tested on Powerware PW3501 hardware. +It also has been tested on PW5110 hardware. EXTRA ARGUMENTS --------------- diff --git a/docs/man/belkinunv.txt b/docs/man/belkinunv.txt index 709eb59536..0bbbb7710c 100644 --- a/docs/man/belkinunv.txt +++ b/docs/man/belkinunv.txt @@ -14,8 +14,8 @@ belkin driver. For information about the core driver, see linkman:nutupsdrv[8]. This driver only supports serial connections. If your UPS has a USB port, -please consult the Hardware Compatibility List (HCL) to see which of the USB -drivers you should use. +please consult the Hardware Compatibility List (HCL) to see which of +the USB drivers you should use. SUPPORTED HARDWARE ------------------ @@ -61,18 +61,18 @@ reboot properly when the power returns. In either case, a deadlock is avoided. In addition, if an optional integer argument is given to the *-x wait* -option, this causes *belkinunv* to wait not only for AC power to be present, -but also for the battery charge to reach the given level. I use this as part of -my startup scripts, to ensure that the batteries are sufficiently charged -before the computer continues booting. This should be put very early in the -startup script, before any filesystems are mounted read/write, and before any -filesystem checks are performed. +option, this causes *belkinunv* to wait not only for AC power to be +present, but also for the battery charge to reach the given level. +I use this as part of my startup scripts, to ensure that the batteries +are sufficiently charged before the computer continues booting. +This should be put very early in the startup script, before any +filesystems are mounted read/write, and before any filesystem +checks are performed. Several other *-x* options are provided to fine-tune this -behavior. See the <<_options,options>> below for detailed descriptions. See the -<<_examples,examples>> -below for examples of how to use *belkinunv* in shutdown and -startup scripts. +behavior. See the <<_options,options>> below for detailed descriptions. +See the <<_examples,examples>> below for examples of how to use *belkinunv* +in shutdown and startup scripts. OPTIONS ------- @@ -82,8 +82,8 @@ See also linkman:nutupsdrv[8] for generic options. Never use the *-x wait*[='level']:: When this option is used, *belkinunv* does not fork into the -background, but behaves as a standalone program. It connects to the UPS and -waits until AC power is present. If 'level' is specified, it also +background, but behaves as a standalone program. It connects to the UPS +and waits until AC power is present. If 'level' is specified, it also waits until the battery charge reaches at least the given level in percent. Then, and only then, *belkinunv* exits. In addition, while *belkinunv* runs in this mode, it displays a status line diff --git a/docs/man/bestfortress.txt b/docs/man/bestfortress.txt index 71d346c4ee..d2b7ef6f4b 100644 --- a/docs/man/bestfortress.txt +++ b/docs/man/bestfortress.txt @@ -16,7 +16,9 @@ linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -This driver supports old Best Fortress UPS equipment using a serial connection. +This driver supports old Best Fortress UPS equipment using a serial +connection. + One example is the "Fortress LI660", sold in (at least) 1995. EXTRA ARGUMENTS diff --git a/docs/man/blazer-common.txt b/docs/man/blazer-common.txt index 9520bcdc75..7124cccdaa 100644 --- a/docs/man/blazer-common.txt +++ b/docs/man/blazer-common.txt @@ -42,27 +42,27 @@ will need changing (see linkman:ups.conf[5]): Maximum battery voltage that is reached after about 12 to 24 hours charging. If you want the driver to report a guesstimated *battery.charge*, you need -to specify this (see <<_battery_charge,BATTERY CHARGE>>). +to specify this (see <<_battery_charge_guesstimation,BATTERY CHARGE GUESSTIMATION>>). *default.battery.voltage.low =* 'value':: Minimum battery voltage just before the UPS automatically shuts down. If you want the driver to report a guesstimated *battery.charge*, you need -to specify this (see <<_battery_charge,BATTERY CHARGE>>). +to specify this (see <<_battery_charge_guesstimation,BATTERY CHARGE GUESSTIMATION>>). *default.battery.voltage.nominal =* 'value':: *override.battery.voltage.nominal =* 'value':: -Some devices show a wrong nominal battery voltage (or none at all), so you may -need to override or set a default value. +Some devices show a wrong nominal battery voltage (or none at all), +so you may need to override or set a default value. *override.battery.packs =* 'value':: Some devices report a part of the total battery voltage. For instance, if *battery.voltage.nominal* is 24 V, but it reports a *battery.voltage* of around 2 V, the number of *battery.packs* to correct this reading would -be 12. The driver will attempt to detect this automatically, but if this fails -somehow, you may want to override this value. +be 12. The driver will attempt to detect this automatically, but if this +fails somehow, you may want to override this value. *ondelay =* 'value':: @@ -103,14 +103,14 @@ seconds at full load and 720 seconds at half load, you would enter The first load should always be higher than the second. If you have values available for loads other than 100 and 50 % respectively, you can use those too, but keep them spaced apart as far as reasonably possible. Just don't -get too close to no load (prediction of runtime depends more on idle load for -the battery then). +get too close to no load (prediction of runtime depends more on idle load +for the battery then). *chargetime =* 'value':: -The time needed to fully recharge the battery after being fully discharged. If -not specified, the driver defaults to 43200 seconds (12 hours). Only used if -*runtimecal* is also specified. +The time needed to fully recharge the battery after being fully discharged. +If not specified, the driver defaults to 43200 seconds (12 hours). +Only used if *runtimecal* is also specified. *idleload =* 'value':: @@ -125,10 +125,10 @@ SERIAL INTERFACE ONLY *cablepower =* 'string':: -By default the driver will set DTR and clear RTS ('normal'). If you find that -your UPS isn't detected or the communication with the UPS is unreliable, you may -try if clear DTR and set RTS ('reverse'), set DTR and RTS ('both') or -clear DTR and RTS ('none') improves this situation. +By default the driver will set DTR and clear RTS ('normal'). If you find +that your UPS isn't detected or the communication with the UPS is unreliable, +you may try if clear DTR and set RTS ('reverse'), set DTR and RTS ('both') +or clear DTR and RTS ('none') improves this situation. endif::blazer_usb[] @@ -141,8 +141,8 @@ include::nut_usb_addvars.txt[] *subdriver =* 'string':: Select a serial-over-USB subdriver to use. You have a choice between *phoenix*, -*ippon*, *cypress*, and *krauler*. When using this option, it is mandatory to also -specify the *vendorid* and *productid*. +*ippon*, *cypress*, and *krauler*. When using this option, it is mandatory +to also specify the *vendorid* and *productid*. *langid_fix =* 'value':: @@ -177,8 +177,8 @@ Turn off the load and return when power is back. Uses the timers defined by *shutdown.stayoff*:: -Turn off the load and remain off (see <<_known_problems,KNOWN PROBLEMS>>). Uses -the timer defined by *offdelay*. +Turn off the load and remain off (see <<_known_problems,KNOWN PROBLEMS>>). +Uses the timer defined by *offdelay*. *shutdown.stop*:: @@ -201,45 +201,48 @@ Perform a battery test for the duration of 'value' minutes. Stop a running battery test (not available on some hardware.) -BATTERY CHARGE --------------- +BATTERY CHARGE GUESSTIMATION +---------------------------- -Due to popular demand, this driver will report a guesstimated *battery.charge* -and optionally *battery.runtime*, provided you specified a couple of the -<<_extra_arguments,EXTRA ARGUMENTS>> listed above. +Due to popular demand, this driver will report a guesstimated +*battery.charge* value and optionally *battery.runtime*, provided you +specified a couple of the <<_extra_arguments,EXTRA ARGUMENTS>> listed above. If you specify both *battery.voltage.high* and *battery.voltage.low* in -linkman:ups.conf[5], but don't enter *runtimecal*, it will guesstimate the state -of charge by looking at the battery voltage alone. This is not reliable under load, -as this only gives reasonably accurate readings if you disconnect the load, let the -battery rest for a couple of minutes and then measure the open cell voltage. This -just isn't practical if the power went out and the UPS is providing power for your +linkman:ups.conf[5], but don't enter *runtimecal*, it will guesstimate +the state of charge by looking at the battery voltage alone. +This is not reliable under load, as this only gives reasonably accurate +readings if you disconnect the load, let the battery rest for a couple +of minutes and then measure the open cell voltage. This just isn't +practical if the power went out and the UPS is providing power for your systems. - battery.voltage - battery.voltage.low -battery.charge = ------------------------------------------ x 100 % - battery.voltage.high - battery.voltage.low - -There is a way to get better readings without disconnecting the load but this -requires one to keep track on how much (and how fast) current is going in- and -out of the battery. If you specified the *runtimecal*, the driver will attempt -to do this. Note however, that this heavily relies on the values you enter and -that the UPS must be able to report the load as well. There are quite a couple -of devices that report 0 % (or any other fixed value) at all times, in which -case this obviously doesn't work. - -The driver also has no way of determining the degradation of the battery capacity -over time, so you'll have to deal with this yourself (by adjusting the values -in *runtimecal*). Also note that the driver guesses the initial state of charge -based on the battery voltage, so this may be less than 100 %, even when you are -certain that they are full. There is just no way to reliably measure this between -0 and 100 % full charge. - -This is better than nothing (but not by much). If any of the above calculations is -giving you incorrect readings, you are the one that put in the values in -linkman:ups.conf[5], so don't complain with the author. If you need something better, -buy a UPS that reports *battery.charge* and *battery.runtime* all by itself -without the help of a NUT driver. + battery.voltage - battery.voltage.low + battery.charge = ------------------------------------------ x 100 % + battery.voltage.high - battery.voltage.low + +There is a way to get better readings without disconnecting the load, +but this requires one to keep track on how much (and how fast) current +is going in- and out of the battery. If you specified the *runtimecal*, +the driver will attempt to do this. Note however, that this heavily +relies on the values you enter and that the UPS must be able to report +the load as well. There are quite a couple of devices that report 0% +(or any other fixed value) at all times, in which case this obviously +doesn't work. + +The driver also has no way of determining the degradation of the battery +capacity over time, so you'll have to deal with this yourself (by adjusting +the values in *runtimecal*). Also note that the driver guesses the initial +state of charge based on the battery voltage, so this may be less than 100%, +even when you are certain that they are full. There is just no way to +reliably measure this between 0 and 100% full charge. + +This is better than nothing (but not by much). If any of the above +calculations are giving you incorrect readings, remember that you are +the one who put in the values in linkman:ups.conf[5], so don't complain +to the author. If you need something better, consider buy an UPS that +reports *battery.charge* and *battery.runtime* all by itself without +the help of a NUT driver. NOTES FOR THE PREVIOUS USER OF MEGATEC DRIVERS @@ -248,11 +251,13 @@ NOTES FOR THE PREVIOUS USER OF MEGATEC DRIVERS The blazer drivers having replaced the megatec ones, some configuration changes may be required by users switching to blazer. -Part of this, the following megatec options, in ups.conf, have to be changed: +Part of this, the following megatec options, in ups.conf, have to be +changed: *battvolts*:: -You need to use 'default.battery.voltage.high' and 'default.battery.voltage.low' +You need to use 'default.battery.voltage.high' and +'default.battery.voltage.low' *dtr and rts*:: @@ -269,16 +274,17 @@ KNOWN PROBLEMS Some UPS commands aren't supported by all models. In most cases, the driver will send a message to the system log when the user tries to execute an -unsupported command. Unfortunately, some models don't even provide a way for -the driver to check for this, so the unsupported commands will silently +unsupported command. Unfortunately, some models don't even provide a way +for the driver to check for this, so the unsupported commands will silently fail. Both the *load.off* and *shutdown.stayoff* instant commands are meant to turn the load off indefinitely. However, some UPS models don't allow this. -Some models report a bogus value for the beeper status (will always be 'enabled' -or 'disabled'). So, the *beeper.toggle* command may appear to have no effect -in the status reported by the driver when, in fact, it is working fine. +Some models report a bogus value for the beeper status (will always be +'enabled' or 'disabled'). So, the *beeper.toggle* command may appear to +have no effect in the status reported by the driver when, in fact, it is +working fine. The temperature and load value is known to be bogus in some models. diff --git a/docs/man/blazer_usb.txt b/docs/man/blazer_usb.txt index d5015429b2..1fa4e8e0dc 100644 --- a/docs/man/blazer_usb.txt +++ b/docs/man/blazer_usb.txt @@ -8,4 +8,3 @@ NAME blazer_usb - Driver for Megatec/Q1 protocol USB based UPS equipment include::blazer-common.txt[] - diff --git a/docs/man/generic_modbus.txt b/docs/man/generic_modbus.txt index 37f9de60c7..6041a76c8d 100644 --- a/docs/man/generic_modbus.txt +++ b/docs/man/generic_modbus.txt @@ -4,7 +4,8 @@ GENERIC_MODBUS(8) NAME ---- -generic_modbus - Driver for contact (direct) signal UPS devices connected via modbus remote I/O gateways +generic_modbus - Driver for contact (direct) signal UPS devices connected +via modbus remote I/O gateways SYNOPSIS -------- @@ -13,8 +14,9 @@ SYNOPSIS *generic_modbus* -a 'DEVICE_NAME' ['OPTIONS'] -NOTE: This man page only documents the specific features of the *generic_modbus* -driver. For information about the core driver, see linkman:nutupsdrv[8]. +NOTE: This man page only documents the specific features of the +*generic_modbus* driver. For information about the core driver, +see linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ diff --git a/docs/man/liebert-esp2.txt b/docs/man/liebert-esp2.txt index e71fb72c39..876f3a5ecd 100644 --- a/docs/man/liebert-esp2.txt +++ b/docs/man/liebert-esp2.txt @@ -17,11 +17,14 @@ SPECIAL CABLING NOTE -------------------- Be aware that an RS-232 cable with ONLY the RX, TX and ground pin -must be used when interfacing with GXT2 series UPS units (and possibly others), -since the handshaking lines are used for purposes other than RS-232 flow control. +must be used when interfacing with GXT2 series UPS units (and possibly +others), since the handshaking lines are used for purposes other than +RS-232 flow control. + Use of a standard RS-232 cable with full handshaking may result in undesired operation and/or shutdown. It is therefore advisable to confirm -the proper cable/wiring with the diagram provided in the manual with your UPS. +the proper cable/wiring with the diagram provided in the manual with your +UPS. SUPPORTED HARDWARE ------------------ @@ -32,8 +35,9 @@ Tested to work on the following units: This is an experimental driver. You have been warned. -This driver currently does not support modification of configuration parameters, -such as the low battery warning time and automatic restart policy. +This driver currently does not support modification of configuration +parameters, such as the low battery warning time and automatic restart +policy. EXTRA ARGUMENTS --------------- @@ -41,7 +45,8 @@ EXTRA ARGUMENTS This driver supports the following optional settings in linkman:ups.conf[5]: *baudrate=*'num':: -Set the speed of the serial connection - 1200, 2400 (default), 4800, 9600 or 19200. +Set the speed of the serial connection - 1200, 2400 (default), 4800, 9600 +or 19200. AUTHORS ------- diff --git a/docs/man/macosx-ups.txt b/docs/man/macosx-ups.txt index 2338be2722..c7140caec3 100644 --- a/docs/man/macosx-ups.txt +++ b/docs/man/macosx-ups.txt @@ -29,8 +29,8 @@ EXTRA ARGUMENTS *port*=auto:: Due to changes in the way that Mac OS X lists power sources, the *port* -parameter no longer has any effect. The rest of NUT still requires a value here, -and our traditional "don't care" value is `auto`. +parameter no longer has any effect. The rest of NUT still requires a value +here, and our traditional "don't care" value is `auto`. *model*='regex':: Likewise, if you have more than one UPS, it may be necessary to specify a @@ -41,8 +41,8 @@ DIAGNOSTICS ----------- If the driver cannot find an UPS, first open System Preferences and see if -there is an "UPS" tab on the Energy Saver panel. If so, re-run the driver with -the *-D* flag to list the names of the power sources found. +there is an "UPS" tab on the Energy Saver panel. If so, re-run the driver +with the *-D* flag to list the names of the power sources found. KNOWN ISSUES AND BUGS --------------------- diff --git a/docs/man/nut-ipmipsu.txt b/docs/man/nut-ipmipsu.txt index 5191ea28d9..fc6a5e4761 100644 --- a/docs/man/nut-ipmipsu.txt +++ b/docs/man/nut-ipmipsu.txt @@ -70,8 +70,10 @@ This driver will report various information related to a PSU, including: - status of the PSU: * 'OL' means that the PSU is present and providing power, - * 'OFF' means that the PSU is present but not providing power (power cable removed), - * 'stale' (no data) means that the PSU is not present (ie physically removed). + * 'OFF' means that the PSU is present but not providing power + (power cable removed), + * 'stale' (no data) means that the PSU is not present (i.e. + physically removed). Here is an example output for a Dell r610 server: diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index 95603603dd..2c4fa456ba 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -53,19 +53,23 @@ Scan all available communication buses (default behavior) List all NUT-compatible USB devices currently plugged in. *-S* | *--snmp_scan*:: -Scan SNMP devices. Requires at least a 'start IP', and optionally, an 'end IP'. See specific SNMP OPTIONS for community and security settings. +Scan SNMP devices. Requires at least a 'start IP', and optionally, +an 'end IP'. See specific SNMP OPTIONS for community and security settings. *-M* | *--xml_scan*:: -Scan XML/HTTP devices. Broadcast a network message on the current network interfaces to retrieve XML/HTTP capable devices. No IP required. +Scan XML/HTTP devices. Can broadcast a network message on the current network +interfaces to retrieve XML/HTTP capable devices. No IP required in this mode. *-O* | *--oldnut_scan*:: Scan NUT devices (i.e. upsd daemon) on IP ranging from 'start IP' to 'end IP'. *-A* | *--avahi_scan*:: -Scan NUT servers using Avahi request on the current network interfaces. No IP required. +Scan NUT servers using Avahi request on the current network interfaces. +No IP required. *-I* | *--ipmi_scan*:: -Scan NUT compatible power supplies available via IPMI on the current host, or over the network. +Scan NUT compatible power supplies available via IPMI on the current host, +or over the network. *-E* | *--eaton_serial* 'serial ports':: Scan Eaton devices (XCP and SHUT) available via serial bus on the current host. @@ -88,10 +92,14 @@ NETWORK OPTIONS Set the network timeout in seconds. Default timeout is 5 seconds. *-s* | *--start_ip* 'start IP':: -Set the first IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). +Set the first IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut) +or optional (XML/HTTP). *-e* | *--end_ip* 'end IP':: -Set the last IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). If this parameter is omitted, only the 'start IP' is scanned. If 'end IP' is less than 'start IP', both parameters are internally permuted. +Set the last IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut) +or optional (XML/HTTP). +If this parameter is omitted, only the 'start IP' is scanned. If 'end IP' is +less than 'start IP', both parameters are internally permuted. *-m* | *--mask_cidr* 'IP address/mask':: Set a range of IP using CIDR notation. @@ -112,43 +120,62 @@ SNMP V3 OPTIONS --------------- *-l* | *--secLevel* 'security level':: -Set the 'security level' used for SNMPv3 messages. Allowed values are: noAuthNoPriv, authNoPriv and authPriv. +Set the 'security level' used for SNMPv3 messages. +Allowed values are: noAuthNoPriv, authNoPriv and authPriv. *-u* | *--secName* 'security name':: -Set the 'security name' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level'. +Set the 'security name' used for authenticated SNMPv3 messages. +This parameter is mandatory if you set 'security level'. *-w* | *--authProtocol* 'authentication protocol':: -Set the 'authentication protocol' used for authenticated SNMPv3 messages. Allowed values are MD5, SHA, SHA256, SHA384 or SHA512 (depending on Net-SNMP library capabilities; check help of the `nut-scanner` binary program for the run-time supported list). Default value is MD5. +Set the 'authentication protocol' used for authenticated SNMPv3 messages. +Allowed values are MD5, SHA, SHA256, SHA384 or SHA512 (depending on +Net-SNMP library capabilities; check help of the `nut-scanner` binary +program for the run-time supported list). Default value is MD5. *-W* | *--authPassword* 'authentication pass phrase':: -Set the 'authentication pass phrase' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level' to authNoPriv or authPriv. +Set the 'authentication pass phrase' used for authenticated SNMPv3 messages. +This parameter is mandatory if you set 'security level' to authNoPriv +or authPriv. *-x* | *--privProtocol* 'privacy protocol':: -Set the 'privacy protocol' used for encrypted SNMPv3 messages. Allowed values are DES, AES, AES192 or AES256 (depending on Net-SNMP library capabilities; check help of the `nut-scanner` binary program for the run-time supported list). Default value is DES. +Set the 'privacy protocol' used for encrypted SNMPv3 messages. +Allowed values are DES, AES, AES192 or AES256 (depending on Net-SNMP +library capabilities; check help of the `nut-scanner` binary program +for the run-time supported list). Default value is DES. *-X* | *--privPassword* 'privacy pass phrase':: -Set the 'privacy pass phrase' used for encrypted SNMPv3 messages. This parameter is mandatory if you set 'security level' to authPriv. +Set the 'privacy pass phrase' used for encrypted SNMPv3 messages. +This parameter is mandatory if you set 'security level' to authPriv. IPMI OPTIONS ------------ *-b* | *--username* 'username':: -Set the username used for authenticating IPMI over LAN connections (mandatory for IPMI over LAN. No default). +Set the username used for authenticating IPMI over LAN connections +(mandatory for IPMI over LAN. No default). *-B* | *--password* 'password':: -Specify the password to use when authenticating with the remote host (mandatory for IPMI over LAN. No default). +Specify the password to use when authenticating with the remote host +(mandatory for IPMI over LAN. No default). *-d* | *--authType* 'authentication type':: -Specify the IPMI 1.5 authentication type to use (NONE, STRAIGHT_PASSWORD_KEY, MD2, and MD5) with the remote host (default=MD5). +Specify the IPMI 1.5 authentication type to use (NONE, STRAIGHT_PASSWORD_KEY, +MD2, and MD5) with the remote host (default=MD5). This forces connection through the 'lan' IPMI interface , thus in IPMI 1.5 mode. *-L* | *--cipher_suite_id* 'cipher suite identifier':: -Specify the IPMI 2.0 cipher suite ID to use. The Cipher Suite ID identifies a set of authentication, integrity, and -confidentiality algorithms to use for IPMI 2.0 communication. The authentication algorithm identifies the algorithm -to use for session setup, the integrity algorithm identifies the algorithm to use for session packet signatures, and the -confidentiality algorithm identifies the algorithm to use for payload encryption (default=3). +Specify the IPMI 2.0 cipher suite ID to use. The Cipher Suite ID identifies +a set of authentication, integrity, and confidentiality algorithms to use +for IPMI 2.0 communication. + -The following cipher suite ids are currently supported (Authentication; Integrity; Confidentiality): +The authentication algorithm identifies the algorithm to use for session +setup, the integrity algorithm identifies the algorithm to use for session +packet signatures, and the confidentiality algorithm identifies the algorithm +to use for payload encryption (default=3). ++ +The following cipher suite ids are currently supported +(Authentication; Integrity; Confidentiality): - *0*: None; None; None - *1*: HMAC-SHA1; None; None @@ -170,7 +197,8 @@ MISCELLANEOUS OPTIONS Display NUT version. *-a* | *--available*:: -Display available bus that can be scanned , depending on how the binary has been compiled. (OLDNUT, USB, SNMP, XML, AVAHI, IPMI). +Display available bus that can be scanned, depending on how the nut-scanner +binary program has been compiled. (OLDNUT, USB, SNMP, XML, AVAHI, IPMI). *-q* | *--quiet*:: Display only scan result. No information on currently scanned bus is displayed. @@ -185,7 +213,8 @@ To scan USB devices only: *nut-scanner -U* -To scan SNMP v1 device with public community on address range 192.168.0.0 to 192.168.0.255: +To scan SNMP v1 device with public community on address range 192.168.0.0 +to 192.168.0.255: *nut-scanner -S -s 192.168.0.0 -e 192.168.0.255* @@ -193,11 +222,13 @@ The same using CIDR notation: *nut-scanner -S -m 192.168.0.0/24* -To scan NUT servers with a timeout of 10 seconds on IP range 192.168.0.0 to 192.168.0.127 using CIDR notation: +To scan NUT servers with a timeout of 10 seconds on IP range 192.168.0.0 +to 192.168.0.127 using CIDR notation: *nut-scanner -O -t 10 -m 192.168.0.0/25* -To scan for power supplies, through IPMI (1.5 mode) over the network, on address range 192.168.0.0 to 192.168.0.255: +To scan for power supplies, through IPMI (1.5 mode) over the network, +on address range 192.168.0.0 to 192.168.0.255 using CIDR notation: *nut-scanner -I -m 192.168.0.0/24 -b username -B password* diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index d23e08c154..c9a9c5d1d9 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -15,18 +15,20 @@ and matching code in tools/nut-scanner/scan_usb.c Some 'value' must be set, typically *auto*. + -NOTE: This could be a device filesystem path like `/dev/usb/hiddev0` but current -use of libusb API precludes knowing and matching by such identifiers. They may -also be inherently unreliable (dependent on re-plugging and enumeration order). -At this time the actual 'value' is ignored, but some 'port' must be there -syntactically. - -It is possible to control multiple UPS units simultaneously by running several -instances of this driver, provided they can be uniquely distinguished by setting -some combination of the *vendor*, *product*, *vendorid*, *productid*, *serial*, -*bus* and/or *device* options detailed +NOTE: This could be a device filesystem path like `/dev/usb/hiddev0` +but current use of libusb API precludes knowing and matching by such +identifiers. They may also be inherently unreliable (dependent on +re-plugging and enumeration order). At this time the actual 'value' +is ignored, but syntactically some 'port' configuration must still +be there. + +It is possible to control multiple UPS units simultaneously by running +several instances of this driver, provided they can be uniquely +distinguished by setting some combination of the *vendor*, *product*, +*vendorid*, *productid*, *serial*, *bus* and/or *device* options detailed below. For devices or operating systems that do not provide sufficient -information, the *allow_duplicates* option can be of use (limited and risky!) +information, the *allow_duplicates* option can be of use (limited and +risky!) *vendorid =* 'regex':: *productid =* 'regex':: diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index 558f105300..633452c718 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -77,11 +77,11 @@ If your UPS doesn't report either *battery.charge* or *battery.runtime* you may *default.battery.voltage.high =* 'value':: Maximum battery voltage that is reached after about 12 to 24 hours charging. -If you want the driver to report a guesstimated *battery.charge*, you need to specify this (see <<_battery_charge,BATTERY CHARGE>>). +If you want the driver to report a guesstimated *battery.charge*, you need to specify this (see <<_battery_charge_guesstimation,BATTERY CHARGE GUESSTIMATION>>). *default.battery.voltage.low =* 'value':: Minimum battery voltage just before the UPS automatically shuts down. -If you want the driver to report a guesstimated *battery.charge*, you need to specify this (see <<_battery_charge,BATTERY CHARGE>>). +If you want the driver to report a guesstimated *battery.charge*, you need to specify this (see <<_battery_charge_guesstimation,BATTERY CHARGE GUESSTIMATION>>). *default.battery.voltage.nominal =* 'value':: *override.battery.voltage.nominal =* 'value':: @@ -484,8 +484,8 @@ Put the UPS in ECO Mode. Take the UPS out of ECO Mode. -BATTERY CHARGE --------------- +BATTERY CHARGE GUESSTIMATION +---------------------------- Due to popular demand, this driver will report a guesstimated *battery.charge* and optionally *battery.runtime*, provided you specified a couple of the <<_extra_arguments,EXTRA ARGUMENTS>> listed above. @@ -493,9 +493,9 @@ If you specify both *battery.voltage.high* and *battery.voltage.low* in linkman: This is not reliable under load, as this only gives reasonably accurate readings if you disconnect the load, let the battery rest for a couple of minutes and then measure the open cell voltage. This just isn't practical if the power went out and the UPS is providing power for your systems. - battery.voltage - battery.voltage.low -battery.charge = ------------------------------------------ x 100 % - battery.voltage.high - battery.voltage.low + battery.voltage - battery.voltage.low + battery.charge = ------------------------------------------ x 100 % + battery.voltage.high - battery.voltage.low There is a way to get better readings without disconnecting the load but this requires one to keep track on how much (and how fast) current is going in and out of the battery. If you specified the *runtimecal*, the driver will attempt to do this. @@ -553,7 +553,7 @@ Part of this, the following bestups options, in linkman:ups.conf[5], are no long *nombattvolt*:: *battvoltmult*:: -See <<_battery_charge,BATTERY CHARGE>>. +See <<_battery_charge_guesstimation,BATTERY CHARGE GUESSTIMATION>>. *ID*:: Discarded. diff --git a/docs/man/nutdrv_siemens_sitop.txt b/docs/man/nutdrv_siemens_sitop.txt index 193f99df44..854a38f883 100644 --- a/docs/man/nutdrv_siemens_sitop.txt +++ b/docs/man/nutdrv_siemens_sitop.txt @@ -16,7 +16,8 @@ linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -*nutdrv_siemens_sitop* supports Siemens UPS models from the SITOP UPS500 series. +*nutdrv_siemens_sitop* supports Siemens UPS models from the SITOP UPS500 +series. Some models have a serial port, others have a USB port. The models with USB port actually contain a serial-over-USB chip, so as far as this driver is concerned, all models are serial models. @@ -94,9 +95,10 @@ POLLING The UPS does not have a special 'get status' command. Instead, it continuously sends out status update messages (tens of messages per second). Every *pollinterval*, these messages are read from the serial port buffer. -In order to react quickly on status changes from the UPS, and to prevent the serial buffer -from overflowing, *pollinterval* should be set to a relatively low value. The recommended -value is 1 (second). + +In order to react quickly on status changes from the UPS, and to prevent +the serial buffer from overflowing, *pollinterval* should be set to a +relatively low value. The recommended value is 1 (second). EXTRA ARGUMENTS --------------- @@ -105,10 +107,10 @@ This driver supports the following optional settings: *max_polls_without_data*='num':: The serial port is polled periodically for new data (see *Polling*). -If there is no valid new data after 'num' polls, it is assumed that communication -with the UPS is lost. -The default value is 2. Lower values may cause spurious 'Data stale' messages, -especially at startup. +If there is no valid new data after 'num' polls, it is assumed that +communication with the UPS is lost. +The default value is 2. Lower values may cause spurious 'Data stale' +messages, especially at startup. INSTANT COMMANDS ---------------- diff --git a/docs/man/powerman-pdu.txt b/docs/man/powerman-pdu.txt index 0332ea64d9..5eeac31064 100644 --- a/docs/man/powerman-pdu.txt +++ b/docs/man/powerman-pdu.txt @@ -69,9 +69,9 @@ The port used to reach 'powermand' is optional if the default port is used. KNOWN ISSUES ------------ -In the current NUT version (2.4.1), ups.status is still exposed, with the value -"WAIT". Some other values from the -ups collection are also exposed. +In the current NUT version as of this writing (2.4.1), ups.status is still +exposed, with the value "WAIT". Some other values from the ups collection +are also exposed. AUTHOR ------ diff --git a/docs/man/socomec_jbus.txt b/docs/man/socomec_jbus.txt index bc192d634e..0563668d56 100644 --- a/docs/man/socomec_jbus.txt +++ b/docs/man/socomec_jbus.txt @@ -4,7 +4,7 @@ SOCOMEC_JBUS(8) NAME ---- -socomec_jbus - Driver for Socomec JBUS UPS with +socomec_jbus - Driver for Socomec JBUS UPS with RS-232 serial Modbus connection. SYNOPSIS @@ -26,7 +26,7 @@ UPS with the following characteristics. 1. Single phase and 3-phase UPS -2. Connection: RS-232 +2. Connection: RS-232 These are typically provided with a Netvision WEB/SNMP management card / external box that would be better served by the linkman:snmp-ups[8] @@ -39,10 +39,10 @@ Currently, it has only been tested on the following model. In theory, any Socomec JBUS model should work. It should be discovered as ``Unknown Socomec JBUS'' with a numeric id that I'll need to add it -to the list of supported UPSs. +to the list of supported UPSs. Sadly, Socomec document only mentions DELPHYS MX and DELPHYS MX elite and -I have the id of my own DIGYS, so chances are, your model will not be +I have the id of my own DIGYS, so chances are, your model will not be recognized but will probably mostly work. Please report successful or unsuccessful results to the bug tracker or the mailing list. Make sure to include the full model number of your UPS manually @@ -54,8 +54,8 @@ CABLING ------- The UPS has an RS-232 port which should be connected with a NULL-modem -cable to a PC serial port. The UPS tested has a female DB9 connector, -so if you construct the cable yourself, make note of the connector type to +cable to a PC serial port. The UPS tested has a female DB9 connector, +so if you construct the cable yourself, make note of the connector type to avoid using gender changers. RS-232 is supported on all operating systems, either via a built-in serial @@ -87,7 +87,7 @@ A built-in serial port can be identified as `/dev/ttyS0` on Linux or one of INSTANT COMMANDS ---------------- -This driver does not (yet?) support sending commands to the UPS. +This driver does not (yet?) support sending commands to the UPS. VARIABLES --------- diff --git a/docs/man/tripplite_usb.txt b/docs/man/tripplite_usb.txt index 06aa7f8b70..92ea4834d4 100644 --- a/docs/man/tripplite_usb.txt +++ b/docs/man/tripplite_usb.txt @@ -40,8 +40,8 @@ This driver has been tested with the following models: * SMART2200RMXL2U * SMART3000RM2U -If you have used Tripp Lite's PowerAlert software to connect to your UPS, there -is a good chance that 'tripplite_usb' will work if it uses one of the +If you have used Tripp Lite's PowerAlert software to connect to your UPS, +there is a good chance that 'tripplite_usb' will work if it uses one of the following protocols: * Protocol 0004 @@ -50,10 +50,10 @@ following protocols: * Protocol 3003 * Protocol 3005 -On the other hand, if the web page for your UPS on the Tripp-Lite website says -"HID-compliant USB port also enables direct integration with built-in power -management and auto-shutdown features of Windows and MAC OS X", then you should -use the linkman:usbhid-ups[8] driver instead. +On the other hand, if the web page for your UPS on the Tripp-Lite website +says "HID-compliant USB port also enables direct integration with built-in +power management and auto-shutdown features of Windows and MAC OS X", then +you should use the linkman:usbhid-ups[8] driver instead. EXTRA ARGUMENTS --------------- @@ -105,22 +105,25 @@ RUNTIME VARIABLES *ups.delay.shutdown*:: -This variable is the same as the 'offdelay' setting, but it can be changed at -runtime by linkman:upsrw[8]. +This variable is the same as the 'offdelay' setting, but it can be +changed at runtime by linkman:upsrw[8]. *ups.id*:: -Some SMARTPRO models feature an ID that can be set and retrieved. If your UPS -supports this feature, this variable will be listed in the output of linkman:upsrw[8]. +Some SMARTPRO models feature an ID that can be set and retrieved. +If your UPS supports this feature, this variable will be listed in +the output of linkman:upsrw[8]. *outlet.1.switch*:: -Some Tripp Lite units have a switchable outlet (usually outlet #1) which can be -turned on and off by writing '1' or '0', respectively, to `outlet.1.switch` -with linkman:upsrw[8]. -If your unit has multiple switchable outlets, substitute the outlet number for -'1' in the variable name. Be sure to test this first - there is no other way to -be certain that the number used by the driver matches the label on the unit. +Some Tripp Lite units have a switchable outlet (usually outlet #1) +which can be turned on and off by writing '1' or '0', respectively, +to `outlet.1.switch` with linkman:upsrw[8]. ++ +If your unit has multiple switchable outlets, substitute the outlet +number for '1' in the variable name. Be sure to test this first -- +there is no other way to be certain that the number used by the driver +matches the label on the unit. KNOWN ISSUES AND BUGS --------------------- diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index 3416728dfa..dcf4c0a1aa 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -9,10 +9,11 @@ ups.conf - UPS definitions for Network UPS Tools DESCRIPTION ----------- -This file is read by the driver controller linkman:upsdrvctl[8], the UPS drivers -that use the common core (see linkman:nutupsdrv[8], and linkman:upsd[8]). The -file begins with global directives, and then each UPS has a section which -contains a number of directives that set parameters for that UPS. +This file is read by the driver controller linkman:upsdrvctl[8], +the UPS drivers which use the common core (see linkman:nutupsdrv[8]), +linkman:nut-driver-enumerator[8], and the NUT data server linkman:upsd[8]. +The file begins with global directives, and then each UPS has a section +which contains a number of directives that set parameters for that UPS. A UPS section begins with the name of the UPS in brackets, and continues until the next UPS name in brackets or until EOF. The name "default" is @@ -94,14 +95,14 @@ The default is 5 seconds. *pollinterval*:: Optional. The status of the UPS will be refreshed after a maximum -delay which is controlled by this setting. This is normally 2 seconds. This -may be useful if the driver is creating too much of a load on your system or -network. +delay which is controlled by this setting. This is normally 2 seconds. +This setting may be useful if the driver is creating too much of a load +on your monitoring system or network. + -Note that some drivers (such as linkman:usbhid-ups[8], linkman:snmp-ups[8] and -linkman:nutdrv_qx[8]) also have an option called *pollfreq* which controls how -frequently some of the less critical parameters are polled. Details are -provided in the respective driver man pages. +Note that some drivers (such as linkman:usbhid-ups[8], linkman:snmp-ups[8] +and linkman:nutdrv_qx[8]) also have an option called *pollfreq* which +controls how frequently some of the less critical parameters are polled. +Details are provided in the respective driver man pages. *synchronous*:: @@ -155,10 +156,10 @@ UPS FIELDS *driver*:: -Required. This specifies which program will be monitoring this UPS. You -need to specify the one that is compatible with your hardware. See -linkman:nutupsdrv[8] for more information on drivers in general and pointers to the -man pages of specific drivers. +Required. This specifies which program will be monitoring this UPS. +You need to specify the one that is compatible with your hardware. +See linkman:nutupsdrv[8] for more information on drivers in general +and pointers to the man pages of specific drivers. *port*:: diff --git a/docs/man/upsclient.txt b/docs/man/upsclient.txt index 0c2ac15ad2..2f78415c84 100644 --- a/docs/man/upsclient.txt +++ b/docs/man/upsclient.txt @@ -70,8 +70,10 @@ SEE ALSO -------- linkman:libupsclient-config[1], -linkman:upscli_init[3], linkman:upscli_cleanup[3], linkman:upscli_add_host_cert[3], -linkman:upscli_connect[3], linkman:upscli_disconnect[3], linkman:upscli_fd[3], +linkman:upscli_init[3], linkman:upscli_cleanup[3], +linkman:upscli_add_host_cert[3], +linkman:upscli_connect[3], linkman:upscli_disconnect[3], +linkman:upscli_fd[3], linkman:upscli_getvar[3], linkman:upscli_list_next[3], linkman:upscli_list_start[3], linkman:upscli_readline[3], linkman:upscli_sendline[3], diff --git a/docs/man/upslog.txt b/docs/man/upslog.txt index 759d8b533e..a35f89baa1 100644 --- a/docs/man/upslog.txt +++ b/docs/man/upslog.txt @@ -88,8 +88,8 @@ ups and logfile separated by commas. An example would be: If started as root, upslog will *setuid*(2) to the user id associated with 'username' for security. + -If 'username' is not defined, it will use the value that was compiled into the -program. This defaults to "nobody", which is less than ideal. +If 'username' is not defined, it will use the value that was compiled into +the program. This defaults to "nobody", which is less than ideal. SERVICE DELAYS -------------- diff --git a/docs/nut.dict b/docs/nut.dict index 97204f47ce..a5e007a6bd 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3078 utf-8 +personal_ws-1.1 en 3080 utf-8 AAS ABI ACFAIL @@ -391,6 +391,7 @@ GPL GPSER GRs GTK +GUESSTIMATION GUIs GWD GXE @@ -1948,6 +1949,7 @@ gtk guardpend guardpstart guesstimate +guesstimation guez gufw gui diff --git a/docs/snmp-subdrivers.txt b/docs/snmp-subdrivers.txt index ca96b4097d..2e124767a4 100644 --- a/docs/snmp-subdrivers.txt +++ b/docs/snmp-subdrivers.txt @@ -224,7 +224,8 @@ To help you, above each entry in -mib.c, there is a comment that displays the textual OID name. For example, the following entry: /* upsMIB.upsObjects.upsIdent.upsIdentModel = STRING: "Dell UPS Tower 1920W HV" */ - { "unmapped.upsidentmodel", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2254.2.4.1.1.0", NULL, SU_FLAG_OK, NULL }, + { "unmapped.upsidentmodel", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.2254.2.4.1.1.0", NULL, SU_FLAG_OK, NULL }, Many times, only the first field will need to be modified, to map to an actual NUT variable name. diff --git a/docs/solaris-usb.txt b/docs/solaris-usb.txt index 486972b723..e96aad085f 100644 --- a/docs/solaris-usb.txt +++ b/docs/solaris-usb.txt @@ -323,7 +323,7 @@ Ap_Id Receptacle Occupant Condition Information When Type Busy Phys_Id -usb10/1 connected configured ok +usb10/1 connected configured ok Mfg: INNO TECH Product: USB to Serial NConfigs: 1 Config: 0 : 20100826 unavailable usb-input n /devices/pci@0,0/pci103c,1609@13:1 ---- diff --git a/scripts/RedHat/README b/scripts/RedHat/README index 4ce4fbe61b..d6023d1295 100644 --- a/scripts/RedHat/README +++ b/scripts/RedHat/README @@ -1,4 +1,3 @@ Install ups in /etc/rc.d/init.d /etc/sysconfig/ups is used only to store the POWERDOWNFLAG variable - diff --git a/scripts/Windows/DriverInstaller/README.txt b/scripts/Windows/DriverInstaller/README.txt index 9eec3d7a82..a8984d5ca5 100644 --- a/scripts/Windows/DriverInstaller/README.txt +++ b/scripts/Windows/DriverInstaller/README.txt @@ -1,3 +1,9 @@ -To easily compile wdi-simple.exe, unzip a copy of libwdi on your disk. -Then set it up to be able to build following http://sourceforge.net/apps/mediawiki/libwdi/index.php?title=Install -Then copy wdi-simple.c and nutscan-usb.h into the "examples" subdirectory of libwdi directory. Finally run ddk_build.cmd from the root of the libwdi directory. +To easily compile `wdi-simple.exe`, unzip a copy of `libwdi` on your disk. + +Then set it up to be able to build following +http://sourceforge.net/apps/mediawiki/libwdi/index.php?title=Install + +Then copy `wdi-simple.c` and `nutscan-usb.h` into the "examples" +subdirectory of libwdi directory. + +Finally run `ddk_build.cmd` from the root of the `libwdi` directory. diff --git a/scripts/Windows/README b/scripts/Windows/README index 3d87a2bd5e..80ebb908e3 100644 --- a/scripts/Windows/README +++ b/scripts/Windows/README @@ -203,7 +203,7 @@ MinGW regex library ^^^^^^^^^^^^^^^^^^^ You can compile it using: - + :; ( cd "$DLDIR" && wget -c http://netcologne.dl.sourceforge.net/project/mingw/Other/UserContributed/regex/mingw-regex-2.5.1/mingw-libgnurx-2.5.1-src.tar.gz ) :; cd "$WSDIR" :; tar xzf "$DLDIR"/mingw-libgnurx-2.5.1-src.tar.gz diff --git a/scripts/augeas/README b/scripts/augeas/README index bfa03d3fa3..9919ab798b 100644 --- a/scripts/augeas/README +++ b/scripts/augeas/README @@ -43,7 +43,7 @@ As an example, on Debian and derivatives, do the following: And optionally: - $ apt-get install libaugeas0 libaugeas-dev python-augeas + $ apt-get install libaugeas0 libaugeas-dev python-augeas On RedHat and derivatives, you have to install the packages 'augeas' and 'augeas-libs'. @@ -155,7 +155,7 @@ ret = aug_save(a); Python ~~~~~~ -The `augeas` class abstracts access to the configuration files. +The `augeas` class abstracts access to the configuration files. $ python Python 2.5.1 (r251:54863, Apr 8 2008, 01:19:33) @@ -201,7 +201,7 @@ Test the conformity testing module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Existing configuration files can be tested for conformity. To do so, use: - + $ augparse -I ./ ./test_nut.aug @@ -218,7 +218,7 @@ driver_name="usbhid-ups" port_name="auto" a = augeas.augeas() - + # Generate nut.conf a.set("/files/etc/nut/nut.conf/MODE", "standalone") diff --git a/scripts/devd/README b/scripts/devd/README index 58f9fda918..71381dce49 100644 --- a/scripts/devd/README +++ b/scripts/devd/README @@ -1,11 +1,12 @@ -On FreeBSD, devd has a similar role to udev on Linux. The devd.conf file -defines actions to perform when devices are plugged in. +On FreeBSD, devd has a similar role to udev on Linux. + +The devd.conf file defines actions to perform when devices are plugged in. The tools/nut-usbinfo.pl script generates nut-usb.conf.in by processing USB macros in all of the drivers. In this case, the defined action for each -matching UPS is to change the permissions such that the NUT drivers can access -the devices without requiring root privileges. You may need to restart devd and -re-plug in the UPS to trigger the actions. +matching UPS is to change the permissions such that the NUT drivers can +access the devices without requiring root privileges. You may need to +restart devd and re-plug in the UPS to trigger the actions. -The format of this configuration file should work with devd on FreeBSD 9.0 and -9.1, at the very least. +The format of this configuration file should work with devd on FreeBSD 9.0 +and 9.1, at the very least. diff --git a/scripts/hotplug/README b/scripts/hotplug/README index 75c7d36717..aa036e72a9 100644 --- a/scripts/hotplug/README +++ b/scripts/hotplug/README @@ -7,8 +7,8 @@ This document introduces Linux Hotplug script for NUT USB drivers (usbhid-ups, bcmxcp_usb and tripplite_usb). These are needed, on older Linux systems, to ensure the right -privileges are set on the usb files (ie allowing nut user to read AND -write to the UPS device). +privileges are set on the usb files (i.e. allowing nut user +to read AND write to the UPS device). Alternative ----------- @@ -20,12 +20,14 @@ Installation ------------ For most users, these files will be automatically installed in -/etc/hotplug upon "make install", if that directory exists. You can -specify an alternate directory by ./configure --with-hotplug-dir=DIR. +/etc/hotplug upon "make install", if that directory exists. +You can specify an alternate directory by running: + + ./configure --with-hotplug-dir=DIR Manual installation ------------------- -These scripts can be used with Linux 2.4 to 2.6.13. +These scripts can be used with Linux 2.4 to 2.6.13. - possibly change libhidups to match NUT user - copy libhidups and libhid.usermap to /etc/hotplug/usb/ @@ -34,4 +36,3 @@ These scripts can be used with Linux 2.4 to 2.6.13. - call update-usb.usermap or equivalent if needed You can then plug your UPS, and start NUT. - diff --git a/scripts/python/README b/scripts/python/README index 9a96e7131e..4c18bedb36 100644 --- a/scripts/python/README +++ b/scripts/python/README @@ -1,19 +1,24 @@ Python NUT Client files ----------------------- -This directory contains various NUT Client related Python scripts, written by -David Goncalves, and released under GPL v3. +This directory contains various NUT Client related Python scripts, written +by David Goncalves, and released under GPL v3. -* "module": this directory contains PyNUT.py, which is a Python abstraction -class to access NUT server(s). You can use it in Python programs to access NUT's +module +~~~~~~ + +This directory contains PyNUT.py, which is a Python abstraction class to +access NUT data server(s). You can use it in Python programs to access NUT's upsd data server in a simple way, without having to know the NUT protocol. + The same module should work for Python 2 and Python 3. -To import it on Python programs you have to use the following (case sensitive) : -'import PyNUT' +To import it on Python programs you have to use the following (case sensitive): -This module provides a 'PyNUTClient' class that can be used to connect and get -data from an upsd data server. + import PyNUT + +This module provides a 'PyNUTClient' class that can be used to connect and +get data from an upsd data server. To install the PyNUT module on Debian/Ubuntu, copy it to: /usr/share/python-support/python-pynut/ @@ -26,8 +31,12 @@ For this to be fully functional, you will need to adapt the login, password and upsname to fit your configuration. A NUT data server should be running for the test program to verify connection and protocol support. +For one practical example, you can research `tests/NIT/nit.sh` in NUT sources. + +app +~~~ -* "app": this directory contains the NUT-Monitor application, that uses the +This directory contains the NUT-Monitor application, which uses the PyNUT class, along with its resources. To install it, you will either need to keep the files together, or to install: diff --git a/scripts/systemd/README b/scripts/systemd/README index b0063581d7..5b3ee5812e 100644 --- a/scripts/systemd/README +++ b/scripts/systemd/README @@ -10,4 +10,3 @@ located in ../upsdrvsvcctl/ source subdirectory. Contributed by Michal Hlavinka Updated 2016-2018 by Michal Hrusecky and Jim Klimov - diff --git a/scripts/udev/README b/scripts/udev/README index ff6a1a0978..c94f834779 100644 --- a/scripts/udev/README +++ b/scripts/udev/README @@ -22,9 +22,11 @@ Installation ------------ For most users, these files will be automatically installed in -/etc/udev (or /lib/udev) upon "make install", if that directory exists and if -the feature (USB and / or IPMI) has been enabled at configure time. You can -specify an alternate directory with ./configure --with-udev-dir=DIR. +/etc/udev (or /lib/udev) upon "make install", if that directory +exists and if the feature (USB and / or IPMI) has been enabled +at configure time. You can specify an alternate directory with: + + ./configure --with-udev-dir=DIR Manual installation ------------------- @@ -32,13 +34,13 @@ Manual installation To install them manually, copy the rules file(s) to /etc/udev/rules.d (or /lib/udev/rules.d on newer systems) using the command(s): -$ cp -f nut-usbups.rules /etc/udev/rules.d/62-nut-usbups.rules -$ cp -f nut-ipmipsu.rules /etc/udev/rules.d/52-nut-ipmipsu.rules + :; cp -f nut-usbups.rules /etc/udev/rules.d/62-nut-usbups.rules + :; cp -f nut-ipmipsu.rules /etc/udev/rules.d/52-nut-ipmipsu.rules You will need to refresh the bus to avoid a reboot for these rules to be active. You can do so using: -$ udevadm trigger --subsystem-match=usb_device + :; udevadm trigger --subsystem-match=usb_device For USB devices, you can then plug your UPS USB cord, or unplug / replug it to refresh the device permission, and start NUT. diff --git a/scripts/ufw/README b/scripts/ufw/README index 701f32386d..5400fe13e8 100644 --- a/scripts/ufw/README +++ b/scripts/ufw/README @@ -26,5 +26,3 @@ For more information, refer to: - link:https://launchpad.net/ufw[UFW project page], - link:https://wiki.ubuntu.com/UncomplicatedFirewall[UFW wiki], - UFW manual page, section APPLICATION INTEGRATION - - diff --git a/tests/NIT/README b/tests/NIT/README index 30da730fdc..729e8a560d 100644 --- a/tests/NIT/README +++ b/tests/NIT/README @@ -13,5 +13,6 @@ See also link:https://git.launchpad.net/ubuntu/+source/nut/tree/debian/tests/test-nut.py[The NUT testing script] available in the link:https://code.edge.launchpad.net/qa-regression-testing[Ubuntu QA Regression Testing suite] +and link:https://salsa.debian.org/debian/nut/-/tree/debian/debian/tests[Debian packaging recipe] doing a similar job with NUT installed from packages and configuring it via files in standard path names. diff --git a/tools/nut-scanner/README b/tools/nut-scanner/README index 1889237eae..043cddff0c 100644 --- a/tools/nut-scanner/README +++ b/tools/nut-scanner/README @@ -24,6 +24,8 @@ functions. Here is a simple example that scans for USB devices, and use its own iteration function to display results: +.Scanning and reporting example +------ #include #include #include @@ -74,7 +76,7 @@ iteration function to display results: exit(EXIT_SUCCESS); } - +------ This library file and the associated header files are not installed by default. You must `./configure --with-dev` to enable building and @@ -91,8 +93,8 @@ referenced in the same file. Configuration helpers ~~~~~~~~~~~~~~~~~~~~~ -NUT provides helper scripts to ease the configuration step of your program, by -detecting the right compilation and link flags. +NUT provides helper scripts to ease the configuration step of your program, +by detecting the right compilation and link flags. For more information, refer to a <>. From ad98d05a42ecc0924fb3f5ce88a487162cb120c2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Jan 2023 18:25:34 +0100 Subject: [PATCH 0351/1232] Revert ".editorconfig: try to neuter additional IntelliJ IDEA formatter [#894]" This reverts commit f9b195a4650766ef81cc4daa35f2d6cee932c87a. --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 1a5e585b2c..93c3ce8293 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,7 +20,7 @@ tab_width = 4 # whose sources must use LF, see .gitattributes ###end_of_line = lf -ij_formatter_enabled = false +#ij_formatter_enabled = false [.editorconfig] trim_trailing_whitespace = false From 44dfe082b03d16ff8f91084f7fae6ae1f5474850 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 18:09:14 +0100 Subject: [PATCH 0352/1232] NEWS: mention instructions for CentOS 6 native NUT 2.8.x builds [#1804] --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 93196ee8f6..f3f7b6ab9e 100644 --- a/NEWS +++ b/NEWS @@ -202,6 +202,8 @@ https://github.com/networkupstools/nut/milestone/8 codebase, and/or prefer non-default system provided implementations (e.g. to use the XPG4 `grep` with `-E` support on Solaris as detailed in https://github.com/networkupstools/nut/issues/1736 comments) + * Build environment configuration notes in `docs/config-prereqs.txt` file + refreshed to cover building of current NUT codebase in CentOS 6 [#1804] - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the From 0d45a724a28d8a1809226d864110ffe2dbd46758 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 18:44:31 +0100 Subject: [PATCH 0353/1232] docs/config-prereqs.txt: document notes about a build for Solaris 8 [#1736, #1738] --- NEWS | 1 + docs/config-prereqs.txt | 87 +++++++++++++++++++++++++++++++++++++++++ docs/nut.dict | 7 +++- 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f3f7b6ab9e..0c08440816 100644 --- a/NEWS +++ b/NEWS @@ -204,6 +204,7 @@ https://github.com/networkupstools/nut/milestone/8 in https://github.com/networkupstools/nut/issues/1736 comments) * Build environment configuration notes in `docs/config-prereqs.txt` file refreshed to cover building of current NUT codebase in CentOS 6 [#1804] + and Solaris 8 [#1736, #1738] - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index abb3167318..1156fde5d3 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -1026,6 +1026,93 @@ NOTE: For Jenkins agents, also need to `pkg install runtime/java/openjdk11` for JRE/JDK 11. Java 11 or 17 is required to run Jenkins agents after summer 2022. +Solaris 8 +~~~~~~~~~ + +Builds for a platform as old as this are not currently covered by CI, however +since the very possibility of doing this was recently verified, some notes +follow. + +For context: Following a discussion in the mailing list starting at +https://alioth-lists.debian.net/pipermail/nut-upsuser/2022-December/013051.html +and followed up by GitHub issues and PR: + +* https://github.com/networkupstools/nut/issues/1736 +* https://github.com/networkupstools/nut/issues/1737 + (about a possible but not yet confirmed platform problem) +* https://github.com/networkupstools/nut/pull/1738 + +...recent NUT codebase was successfully built and self-tested in a Solaris 8 +x86 VM (a circa 2002 release), confirming the project's adherence to the +goal that if NUT ran on a platform earlier, so roughly anything POSIX-ish +released this millennium and still running, it should still be possible -- +at least as far as our part of equation is concerned. + +That said, platform shows its age vs. later standards (script interpreters +and other tools involved), and base "complete install" lacked compilers, +so part of the tested build platform setup involved third-party provided +package repositories. + +One helpful project was extensive notes about preparation of the Solaris 8 VM +(and our further comments there), which pointed to the still active "tgcware" +repository and contains scripts to help prepare the freshly installed system: + +* https://github.com/mac-65/Solaris_8_x86_VM +* https://github.com/mac-65/Solaris_8_x86_VM/issues/1 +* http://jupiterrise.com/tgcware/sunos5.8_x86/stable/ + +Note that scripts attached to the notes refer to older versions of the +packages than what is currently published, so I ended up downloading +everything from the repository into the VM and using shell wildcards +to pick the packages to install (mind the package families with similar +names when preparing such patterns). + +After the OS, tools and feasible third-party dependencies were installed, +certain environment customization was needed to prepare for NUT build in +particular (originally detailed in GitHub issues linked above): + +* For `CONFIG_SHELL`, system `dtksh` seems to support the syntax (unlike + default `/bin/sh`), but for some reason segfaults during `configure` tests. + Alternatively `/usr/tgcware/bin/bash` (4.4-ish) can be used successfully. + System-provided bash 2.x is too old for these scripts. +* To run `ci_build.sh` CI/dev-testing helper script, either the shebang + should be locally fixed to explicitly call `/usr/tgcware/bin/bash`, or + the build environment's `PATH` should point to this `bash` implementation + as a first hit. If we want to primarily use OS-provided tools, this latter + option may need a bit of creative setup; I made a symlink into the + `/usr/lib/ccache` directory which has to be first anyway (before compilers). +* The system-provided default `grep` lacks the `-E` option which was preferred + over generally obsoleted `egrep` since + link:https://github.com/networkupstools/nut/pull/1660[PR #1660] -- however + pre-pending `/usr/xpg4/bin` early in the `PATH` fixes the problem. +* The builds of `gcc` in TGCWARE repository were picky about shared objects + linking as needed to run them, so `LD_LIBRARY_PATH` had to refer to its + library directories (generally this is frowned upon and should be a last + resort). +* Due to lack of Python in that OS release, NUT augeas support had to be + disabled when preparing the build from Git sources (generated files may + be available as part of distribution tarballs however): + `WITHOUT_NUT_AUGEAS=true; export WITHOUT_NUT_AUGEAS; ./autogen.sh` + +Overall, the successful test build using the NUT standard CI helper script +`ci_build.sh` had the following shell session settings: + +---- +### Common pre-sets from .profile or .bashrc: +### bash-2.03$ echo $PATH +### /usr/bin:/usr/dt/bin:/usr/openwin/bin:/bin:/usr/ucb:/usr/tgcware/bin:/usr/tgcware/gnu:/usr/tgcware/gcc42/bin:/usr/tgcware/i386-pc-solaris2.8/bin + +### bash-2.03$ echo $LD_LIBRARY_PATH +### /usr/lib:/usr/tgcware/lib:/usr/tgcware/gcc42/lib:/usr/tgcware/i386-pc-solaris2.8/lib + +### Further tuning for the build itself: +:; git clean -fffdddxxx +:; CONFIG_SHELL=/usr/tgcware/bin/bash \ + WITHOUT_NUT_AUGEAS=true \ + PATH="/usr/xpg4/bin:$PATH" \ + /usr/tgcware/bin/bash ./ci_build.sh +---- + MacOS with homebrew ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/nut.dict b/docs/nut.dict index a5e007a6bd..8fb2e88371 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3080 utf-8 +personal_ws-1.1 en 3087 utf-8 AAS ABI ACFAIL @@ -1797,6 +1797,7 @@ dsssl dstate dt dtds +dtksh dtr du dumbterm @@ -1874,6 +1875,7 @@ fds fe fenton fentonups +fffdddxxx ffff fi fieldset @@ -2067,6 +2069,7 @@ ipmipsu ippon ipv isbmex +ish iso isolator ivtscd @@ -2827,6 +2830,7 @@ testime testtime testuser textproc +tgcware th timeframe timehead @@ -3059,6 +3063,7 @@ xhtml xmalloc xml xmllint +xpg xr xrealloc xsl From 0c9276444fb041ac6ffd7134374cf7b8c4e9bfaa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 20:49:09 +0100 Subject: [PATCH 0354/1232] nut-scanner: report bogus and duplicate serial numbers [#1810] --- NEWS | 4 + UPGRADING | 4 + docs/man/Makefile.am | 9 + docs/man/nut-scanner.txt | 4 + docs/man/nutscan.txt | 7 +- docs/man/nutscan_add_option_to_device.txt | 9 + docs/man/nutscan_cidr_to_ip.txt | 1 + docs/man/nutscan_display_parsable.txt | 7 + docs/man/nutscan_display_sanity_check.txt | 39 ++++ .../nutscan_display_sanity_check_serial.txt | 43 ++++ docs/man/nutscan_display_ups_conf.txt | 6 + ...can_display_ups_conf_with_sanity_check.txt | 36 ++++ docs/man/nutscan_free_device.txt | 1 + docs/man/nutscan_get_serial_ports_list.txt | 1 + docs/man/nutscan_init.txt | 3 + docs/man/nutscan_new_device.txt | 3 + docs/man/nutscan_scan_avahi.txt | 3 + docs/man/nutscan_scan_eaton_serial.txt | 3 + docs/man/nutscan_scan_ipmi.txt | 6 +- docs/man/nutscan_scan_nut.txt | 6 +- docs/man/nutscan_scan_snmp.txt | 6 +- docs/man/nutscan_scan_usb.txt | 6 +- docs/man/nutscan_scan_xml_http_range.txt | 6 +- tools/nut-scanner/nut-scan.h | 6 + tools/nut-scanner/nut-scanner.c | 12 +- tools/nut-scanner/nutscan-display.c | 183 ++++++++++++++++++ 26 files changed, 405 insertions(+), 9 deletions(-) create mode 100644 docs/man/nutscan_display_sanity_check.txt create mode 100644 docs/man/nutscan_display_sanity_check_serial.txt create mode 100644 docs/man/nutscan_display_ups_conf_with_sanity_check.txt diff --git a/NEWS b/NEWS index 17f42d52ce..fba4e94833 100644 --- a/NEWS +++ b/NEWS @@ -184,6 +184,10 @@ https://github.com/networkupstools/nut/milestone/8 abort and require either to install the dependency or explicitly forfeit the tool (some distro packages missed it quietly in the past) [#1560] + - The `nut-scanner` program should now by default warn about serial numbers + which do not make much sense (are duplicate, empty, all same character, etc) + [#1810] + - Existing openssl-1.1.0 support added for NUT v2.8.0 release was tested to be sufficient without deprecation warnings for builds against openssl-3.0.x (but no real-time testing was done yet) [#1547] diff --git a/UPGRADING b/UPGRADING index 701d8412c4..85d4ea7769 100644 --- a/UPGRADING +++ b/UPGRADING @@ -31,6 +31,10 @@ Changes from 2.8.0 to 2.8.1 device configuration [#1790]: hopefully these would now suffice for sufficiently unique combinations; + * The `nut-scanner` tool should also suggest sanity-check violations + as comments in its generated device configuration [#1810], e.g. bogus + or duplicate serial number values; + * The common USB matching logic was updated with an `allow_duplicates` flag (caveat emptor!) which may help monitor several related no-name devices on systems that do not discern "bus" and "device" values diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 146e7c525c..3dcf7f609b 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -177,6 +177,9 @@ SRC_DEV_PAGES = \ nutscan_scan_avahi.txt \ nutscan_scan_ipmi.txt \ nutscan_scan_eaton_serial.txt \ + nutscan_display_sanity_check.txt \ + nutscan_display_sanity_check_serial.txt \ + nutscan_display_ups_conf_with_sanity_check.txt \ nutscan_display_ups_conf.txt \ nutscan_display_parsable.txt \ nutscan_cidr_to_ip.txt \ @@ -290,6 +293,9 @@ MAN3_DEV_PAGES = \ nutscan_scan_avahi.3 \ nutscan_scan_ipmi.3 \ nutscan_scan_eaton_serial.3 \ + nutscan_display_sanity_check.3 \ + nutscan_display_sanity_check_serial.3 \ + nutscan_display_ups_conf_with_sanity_check.3 \ nutscan_display_ups_conf.3 \ nutscan_display_parsable.3 \ nutscan_cidr_to_ip.3 \ @@ -352,6 +358,9 @@ HTML_DEV_MANS = \ nutscan_scan_avahi.html \ nutscan_scan_ipmi.html \ nutscan_scan_eaton_serial.html \ + nutscan_display_sanity_check.html \ + nutscan_display_sanity_check_serial.html \ + nutscan_display_ups_conf_with_sanity_check.html \ nutscan_display_ups_conf.html \ nutscan_display_parsable.html \ nutscan_cidr_to_ip.html \ diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index 95603603dd..b4e6e543db 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -37,6 +37,10 @@ Display the help text. DISPLAY OPTIONS --------------- +*-Q* | *--disp_nut_conf_with_sanity_check*:: +Display result in the 'ups.conf' format with sanity-check warnings (if any) +as comments (default). + *-N* | *--disp_nut_conf*:: Display result in the 'ups.conf' format. diff --git a/docs/man/nutscan.txt b/docs/man/nutscan.txt index 99cb2471e2..bfef09f52b 100644 --- a/docs/man/nutscan.txt +++ b/docs/man/nutscan.txt @@ -43,7 +43,9 @@ linkman:nutscan_add_device_to_device[3]. Helper functions are also provided to output data using standard formats: - linkman:nutscan_display_parsable[3] for parsable output, -- linkman:nutscan_display_ups_conf[3] for ups.conf style. +- linkman:nutscan_display_ups_conf[3] for ups.conf style, +- linkman:nutscan_display_ups_conf_with_sanity_check[3] for ups.conf style + with comments for warnings about possible configuration problems (if any). ERROR HANDLING @@ -59,6 +61,9 @@ linkman:nut-scanner[8], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_display_ups_conf[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_device_to_device[3], diff --git a/docs/man/nutscan_add_option_to_device.txt b/docs/man/nutscan_add_option_to_device.txt index 2dbf6690c0..b7a5262402 100644 --- a/docs/man/nutscan_add_option_to_device.txt +++ b/docs/man/nutscan_add_option_to_device.txt @@ -38,6 +38,12 @@ associated 'value'. Copies of 'option_name' and 'value' are stored in the device, so the caller can safely free both of the original strings used as arguments. +Such options and their values may be further sanity-checked and reported +as warnings by *nutscan_display_sanity_check()* dispatcher and its related +methods which implement the logic of particular checks. This is used for +example when generating 'ups.conf' file content suggestions with +*nutscan_display_ups_conf_with_sanity_check()* method. + NOTES ----- @@ -49,6 +55,9 @@ SEE ALSO linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_device_to_device[3] diff --git a/docs/man/nutscan_cidr_to_ip.txt b/docs/man/nutscan_cidr_to_ip.txt index 5f18213eeb..ef7c9a9c1a 100644 --- a/docs/man/nutscan_cidr_to_ip.txt +++ b/docs/man/nutscan_cidr_to_ip.txt @@ -40,4 +40,5 @@ SEE ALSO linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_display_ups_conf[3] diff --git a/docs/man/nutscan_display_parsable.txt b/docs/man/nutscan_display_parsable.txt index 9e275153be..aa2cc76e4b 100644 --- a/docs/man/nutscan_display_parsable.txt +++ b/docs/man/nutscan_display_parsable.txt @@ -29,12 +29,19 @@ which is: * and depend on , see the corresponding driver's man page. +Note that this format is for machine consumption, so is not associated +with sanity checks that may be used along with display method for the +'ups.conf' file format. + SEE ALSO -------- linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_ups_conf[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3] diff --git a/docs/man/nutscan_display_sanity_check.txt b/docs/man/nutscan_display_sanity_check.txt new file mode 100644 index 0000000000..f0e6ce4eb0 --- /dev/null +++ b/docs/man/nutscan_display_sanity_check.txt @@ -0,0 +1,39 @@ +NUTSCAN_DISPLAY_SANITY_CHECK(3) +=============================== + +NAME +---- + +nutscan_display_sanity_check - Display sanity check warnings about +the specified `nutscan_device_t` structure on stdout. + +SYNOPSIS +-------- + + #include + + void nutscan_display_sanity_check(nutscan_device_t * device); + +DESCRIPTION +----------- + +The *nutscan_display_sanity_check()* function calls all sanity-check +analyzers against displays all NUT devices in 'device', and they may +print comments to stdout. It displays them in a way that it can be +directly copied into the 'ups.conf' file. + +It is called from *nutscan_display_ups_conf_with_sanity_check()* to +provide an aggregate content for 'ups.conf' file in one shot. + +SEE ALSO +-------- + +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], +linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], +linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], +linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], +linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3] diff --git a/docs/man/nutscan_display_sanity_check_serial.txt b/docs/man/nutscan_display_sanity_check_serial.txt new file mode 100644 index 0000000000..243b15a341 --- /dev/null +++ b/docs/man/nutscan_display_sanity_check_serial.txt @@ -0,0 +1,43 @@ +NUTSCAN_DISPLAY_SANITY_CHECK_SERIAL(3) +====================================== + +NAME +---- + +nutscan_display_sanity_check_serial - Display sanity check warnings +about "serial" (serial number/code string) optional values in the +specified `nutscan_device_t` structure on stdout. + +SYNOPSIS +-------- + + #include + + void nutscan_display_sanity_check_serial(nutscan_device_t * device); + +DESCRIPTION +----------- + +The *nutscan_display_sanity_check_serial()* function analyzes "serial" +optional field in all NUT devices in 'device', and in case of duplicate +or otherwise seemingly invalid values, prints comments to stdout. +It displays them in a way that it can be directly copied into the +'ups.conf' file. + +It is called from *nutscan_display_ups_conf_with_sanity_check()* to +provide an aggregate content for 'ups.conf' file in one shot. + +SEE ALSO +-------- + +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], +linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], +linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], +linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], +linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3] diff --git a/docs/man/nutscan_display_ups_conf.txt b/docs/man/nutscan_display_ups_conf.txt index b79c90fa0c..3b6233ac9d 100644 --- a/docs/man/nutscan_display_ups_conf.txt +++ b/docs/man/nutscan_display_ups_conf.txt @@ -21,12 +21,18 @@ The *nutscan_display_ups_conf()* function displays all NUT devices in 'device' to stdout. It displays them in a way that it can be directly copied into the 'ups.conf' file. +It is called from *nutscan_display_ups_conf_with_sanity_check()* to +provide an aggregate content for 'ups.conf' file in one shot. + SEE ALSO -------- linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3] diff --git a/docs/man/nutscan_display_ups_conf_with_sanity_check.txt b/docs/man/nutscan_display_ups_conf_with_sanity_check.txt new file mode 100644 index 0000000000..838375eb36 --- /dev/null +++ b/docs/man/nutscan_display_ups_conf_with_sanity_check.txt @@ -0,0 +1,36 @@ +NUTSCAN_DISPLAY_UPS_CONF_WITH_SANITY_CHECK(3) +============================================= + +NAME +---- + +nutscan_display_ups_conf_with_sanity_check - Display the specified +`nutscan_device_t` structure and sanity-check warnings on stdout. + +SYNOPSIS +-------- + + #include + + void nutscan_display_ups_conf_with_sanity_check(nutscan_device_t * device); + +DESCRIPTION +----------- + +The *nutscan_display_ups_conf_with_sanity_check()* function displays +all NUT devices in 'device' to stdout, and follows up with comments +about sanity-check violations (if any). It displays them in a way that +it can be directly copied into the 'ups.conf' file. + +SEE ALSO +-------- + +linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], +linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], +linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], +linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], +linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3] diff --git a/docs/man/nutscan_free_device.txt b/docs/man/nutscan_free_device.txt index 4420f362e2..7ef10cc3ad 100644 --- a/docs/man/nutscan_free_device.txt +++ b/docs/man/nutscan_free_device.txt @@ -32,6 +32,7 @@ SEE ALSO linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3] diff --git a/docs/man/nutscan_get_serial_ports_list.txt b/docs/man/nutscan_get_serial_ports_list.txt index 8b38bedbbf..bf8aa26d89 100644 --- a/docs/man/nutscan_get_serial_ports_list.txt +++ b/docs/man/nutscan_get_serial_ports_list.txt @@ -56,4 +56,5 @@ linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_eaton_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_display_ups_conf[3] diff --git a/docs/man/nutscan_init.txt b/docs/man/nutscan_init.txt index 17e6ddf91d..6d372e0ce3 100644 --- a/docs/man/nutscan_init.txt +++ b/docs/man/nutscan_init.txt @@ -46,6 +46,9 @@ linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3] diff --git a/docs/man/nutscan_new_device.txt b/docs/man/nutscan_new_device.txt index 81cf26d164..43581599ec 100644 --- a/docs/man/nutscan_new_device.txt +++ b/docs/man/nutscan_new_device.txt @@ -37,5 +37,8 @@ linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_snmp[3] linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3] +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3] linkman:nutscan_add_device_to_device[3] diff --git a/docs/man/nutscan_scan_avahi.txt b/docs/man/nutscan_scan_avahi.txt index 01f02e9e92..5c407d3d7b 100644 --- a/docs/man/nutscan_scan_avahi.txt +++ b/docs/man/nutscan_scan_avahi.txt @@ -41,6 +41,9 @@ linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_cidr_to_ip[3], diff --git a/docs/man/nutscan_scan_eaton_serial.txt b/docs/man/nutscan_scan_eaton_serial.txt index 068db12877..42e2a826ec 100644 --- a/docs/man/nutscan_scan_eaton_serial.txt +++ b/docs/man/nutscan_scan_eaton_serial.txt @@ -40,6 +40,9 @@ linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], diff --git a/docs/man/nutscan_scan_ipmi.txt b/docs/man/nutscan_scan_ipmi.txt index 9d463f477d..a1fddcfce8 100644 --- a/docs/man/nutscan_scan_ipmi.txt +++ b/docs/man/nutscan_scan_ipmi.txt @@ -50,7 +50,11 @@ SEE ALSO linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], -linkman:nutscan_scan_snmp[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_scan_snmp[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3], diff --git a/docs/man/nutscan_scan_nut.txt b/docs/man/nutscan_scan_nut.txt index 7d0b543c84..08c6520c88 100644 --- a/docs/man/nutscan_scan_nut.txt +++ b/docs/man/nutscan_scan_nut.txt @@ -46,7 +46,11 @@ SEE ALSO linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_avahi[3], -linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_scan_ipmi[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3], diff --git a/docs/man/nutscan_scan_snmp.txt b/docs/man/nutscan_scan_snmp.txt index ecc893ffb9..3ae72ccfd1 100644 --- a/docs/man/nutscan_scan_snmp.txt +++ b/docs/man/nutscan_scan_snmp.txt @@ -82,7 +82,11 @@ SEE ALSO linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], -linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_scan_ipmi[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3], diff --git a/docs/man/nutscan_scan_usb.txt b/docs/man/nutscan_scan_usb.txt index 878c712a92..25d2b6ddb0 100644 --- a/docs/man/nutscan_scan_usb.txt +++ b/docs/man/nutscan_scan_usb.txt @@ -33,7 +33,11 @@ SEE ALSO linkman:nutscan_init[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_xml_http_range[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], -linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_scan_ipmi[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3] diff --git a/docs/man/nutscan_scan_xml_http_range.txt b/docs/man/nutscan_scan_xml_http_range.txt index 15cb2af5c1..70e0a86b23 100644 --- a/docs/man/nutscan_scan_xml_http_range.txt +++ b/docs/man/nutscan_scan_xml_http_range.txt @@ -48,7 +48,11 @@ SEE ALSO linkman:nutscan_init[3], linkman:nutscan_scan_usb[3], linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3], -linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3], +linkman:nutscan_scan_ipmi[3], +linkman:nutscan_display_sanity_check[3], +linkman:nutscan_display_sanity_check_serial[3], +linkman:nutscan_display_ups_conf_with_sanity_check[3], +linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3], linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3], linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3] diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index d71d690c01..ae5f8f42cd 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -4,6 +4,7 @@ * 2012 - Arnaud Quette * 2016 - EATON - IP addressed XML scan * 2016-2021 - EATON - Various threads-related improvements + * 2023 - Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -172,6 +173,11 @@ sem_t * nutscan_semaphore(void); void nutscan_display_ups_conf(nutscan_device_t * device); void nutscan_display_parsable(nutscan_device_t * device); +/* Display sanity-check concerns for various fields etc. (if any) */ +void nutscan_display_ups_conf_with_sanity_check(nutscan_device_t * device); +void nutscan_display_sanity_check(nutscan_device_t * device); +void nutscan_display_sanity_check_serial(nutscan_device_t * device); + #ifdef __cplusplus /* *INDENT-OFF* */ } diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index c1b76a09ac..05e28f7d00 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2011 - 2012 Arnaud Quette * Copyright (C) 2016 Michal Vyskocil - * Copyright (C) 2016 - 2021 Jim Klimov + * Copyright (C) 2016 - 2023 Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,7 +61,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:NPqIVaD"; +static const char optstring[] = "?ht:T:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:QNPqIVaD"; #ifdef HAVE_GETOPT_LONG static const struct option longopts[] = { @@ -90,6 +90,7 @@ static const struct option longopts[] = { { "oldnut_scan", no_argument, NULL, 'O' }, { "avahi_scan", no_argument, NULL, 'A' }, { "ipmi_scan", no_argument, NULL, 'I' }, + { "disp_nut_conf_with_sanity_check", no_argument, NULL, 'Q' }, { "disp_nut_conf", no_argument, NULL, 'N' }, { "disp_parsable", no_argument, NULL, 'P' }, { "quiet", no_argument, NULL, 'q' }, @@ -329,6 +330,7 @@ static void show_usage() printf("\nNUT specific options:\n"); printf(" -p, --port : Port number of remote NUT upsd\n"); printf("\ndisplay specific options:\n"); + printf(" -Q, --disp_nut_conf_with_sanity_check: Display result in the ups.conf format with sanity-check warnings as comments (default)\n"); printf(" -N, --disp_nut_conf: Display result in the ups.conf format\n"); printf(" -P, --disp_parsable: Display result in a parsable format\n"); printf("\nMiscellaneous options:\n"); @@ -413,7 +415,8 @@ int main(int argc, char *argv[]) nutscan_init(); - display_func = nutscan_display_ups_conf; + /* Default, see -Q/-N/-P below */ + display_func = nutscan_display_ups_conf_with_sanity_check; /* Parse command line options -- Second loop: everything else */ /* Restore error messages... */ @@ -631,6 +634,9 @@ int main(int argc, char *argv[]) } allow_ipmi = 1; break; + case 'Q': + display_func = nutscan_display_ups_conf_with_sanity_check; + break; case 'N': display_func = nutscan_display_ups_conf; break; diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index 71f2248b15..e31d05f1dd 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 - EATON + * 2023 - Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +26,7 @@ #include #include "nutscan-device.h" #include "nut-scan.h" +#include "nut_stdint.h" static char * nutscan_device_type_string[TYPE_END] = { "NONE", @@ -37,6 +39,12 @@ static char * nutscan_device_type_string[TYPE_END] = { "EATON_SERIAL" }; +void nutscan_display_ups_conf_with_sanity_check(nutscan_device_t * device) +{ + nutscan_display_ups_conf(device); + nutscan_display_sanity_check(device); +} + void nutscan_display_ups_conf(nutscan_device_t * device) { nutscan_device_t * current_dev = device; @@ -119,3 +127,178 @@ void nutscan_display_parsable(nutscan_device_t * device) } while (current_dev != NULL); } + +/* TODO: If this is ever a memory-pressure problem, + * e.g. if preparing to monitor hundreds of devices, + * can convert to dynamically allocated (and freed) + * strings. For now go for speed with static arrays. + */ +typedef struct keyval_strings { + char key[SMALLBUF]; + char val[LARGEBUF]; +} keyval_strings_t; + +void nutscan_display_sanity_check_serial(nutscan_device_t * device) +{ + /* Some devices have useless serial numbers + * (empty strings, all-zeroes, all-spaces etc.) + * and others have identical serial numbers on + * physically different hardware units. + * Warn about these as a possible problem e.g. + * for matching and discerning devices generally. + * Note that we may also have multiple data paths + * to the same device (e.g. monitored over USB + * and SNMP, so the situation is not necessarily + * a problem). + * Also note that not all devices may have/report + * a serial at all (option will be missing). + */ + nutscan_device_t * current_dev = device; + nutscan_options_t * opt; + int nutdev_num = 1; + size_t listlen = 0, count = 0, i; + keyval_strings_t *map = NULL, *entry = NULL; + + if (device == NULL) { + return; + } + + /* Find end of the list */ + while (current_dev->next != NULL) { + current_dev = current_dev->next; + } + + /* Find start of the list and count its size */ + while (current_dev->prev != NULL) { + current_dev = current_dev->prev; + listlen++; + } + + /* Empty? No bogus data or conflicts at least... */ + if (!listlen) { + return; + } + + /* Process each device: + * Build a map of "serial"=>"nutdevX[,...,nutdevZ]" + * and warn if there are bogus "serial" keys or if + * there are several nutdev's (a comma in value). + */ + + /* Reserve enough slots for all-unique serials */ + map = calloc(sizeof(keyval_strings_t), listlen); + if (map == NULL) { + fprintf(stderr, "%s: Memory allocation error, skipped\n", __func__); + return; + } + + do { + /* Look for serial option in current device */ + opt = current_dev->opt; + + while (NULL != opt) { + if (opt->option != NULL && !strcmp(opt->option, "serial")) { + /* This nutdevX has a serial; is it in map already? */ + char keytmp[SMALLBUF]; + snprintf(keytmp, sizeof(keytmp), "%s", + opt->value ? (opt->value[0] ? opt->value : "") : ""); + + for (i = 0, entry = NULL; i < listlen && map[i].key[0] != '\0'; i++) { + if (!strncmp(map[i].key, keytmp, sizeof(map[i].key))) { + entry = &(map[i]); + break; + } + } + + if (entry) { + /* Got a hit => append value */ + /* TODO: If changing from preallocated LARGEBUF to + * dynamic allocation, malloc data for larger "val". + */ + snprintfcat(entry->val, sizeof(entry->val), + ",nutdev%i", nutdev_num); + } else { + /* No hit => new key */ + /* TODO: If changing from preallocated LARGEBUF to + * dynamic allocation, malloc data for new "entry" + * and its key/val fields. + */ + entry = &(map[i]); + + count++; + if (count != i || count > listlen) { + /* Should never get here, but just in case... */ + fprintf(stderr, "%s: Loop overflow, skipped\n", __func__); + goto exit; + } + + snprintf(entry->key, sizeof(entry->key), + "%s", keytmp); + snprintf(entry->val, sizeof(entry->val), + "nutdev%i", nutdev_num); + } + + /* Abort the opt-searching loop for this device */ + goto next; + } + opt = opt->next; + } + +next: + nutdev_num++; + + current_dev = current_dev->next; + } + while (current_dev != NULL); + + if (!count) { + /* No serials in found devices? Oh well */ + goto exit; + } + + /* Now look for red flags in the map */ + /* FIXME: Weed out special chars to avoid breaking comment-line markup? + * Thinking of ASCII control codes < 32 including CR/LF, and codes 128+... */ + for (i = 0; i < count; i++) { + size_t j; + entry = &(map[i]); + + /* NULL or empty serials */ + if (!strcmp(entry->key, "") || !strcmp(entry->key, "")) { + printf("\n# WARNING: %s \"serial\" reported in some devices: %s\n", + entry->key, entry->val); + continue; + } + + /* All chars in "serial" are same (zero, space, etc.) */ + for (j = 0; entry->key[j] != '\0' && entry->key[j] == entry->key[0]; j++); + if (j > 0 && entry->key[j] == '\0') { + printf("\n# WARNING: all-same character \"serial\" " + "with %" PRIuSIZE " copies of '%c' (0x%02X) " + "reported in some devices: %s\n", + j, entry->key[0], entry->key[0], entry->val); + continue; + } + + /* Duplicates (maybe same device, maybe not) */ + for (j = 0; entry->val[j] != '\0' && entry->val[j] != ','; j++); + if (j > 0 && entry->key[j] != '\0') { + printf("\n# WARNING: same \"serial\" value \"%s\" " + "reported in several device configurations " + "(maybe okay if multiple drivers for same device, " + "likely a vendor bug if reported by same driver " + "for many devices): %s\n", + entry->key, entry->val); + continue; + } + } + +exit: + free (map); +} + +void nutscan_display_sanity_check(nutscan_device_t * device) +{ + /* Extend the list later as more sanity-checking appears */ + nutscan_display_sanity_check_serial(device); +} From 040df4db5f9126d069707aadf79de77f3a69807f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 23:43:26 +0100 Subject: [PATCH 0355/1232] tools/nut-scanner/nutscan-display.c: trace entry into the display methods [#1810] --- tools/nut-scanner/nutscan-display.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index e31d05f1dd..fdadd37f81 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -41,6 +41,9 @@ static char * nutscan_device_type_string[TYPE_END] = { void nutscan_display_ups_conf_with_sanity_check(nutscan_device_t * device) { + upsdebugx(2, "%s: %s", __func__, device + ? (device->type < TYPE_END ? nutscan_device_type_string[device->type] : "") + : ""); nutscan_display_ups_conf(device); nutscan_display_sanity_check(device); } @@ -51,6 +54,10 @@ void nutscan_display_ups_conf(nutscan_device_t * device) nutscan_options_t * opt; static int nutdev_num = 1; + upsdebugx(2, "%s: %s", __func__, device + ? (device->type < TYPE_END ? nutscan_device_type_string[device->type] : "") + : ""); + if (device == NULL) { return; } @@ -91,6 +98,10 @@ void nutscan_display_parsable(nutscan_device_t * device) nutscan_device_t * current_dev = device; nutscan_options_t * opt; + upsdebugx(2, "%s: %s", __func__, device + ? (device->type < TYPE_END ? nutscan_device_type_string[device->type] : "") + : ""); + if (device == NULL) { return; } @@ -159,6 +170,10 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) size_t listlen = 0, count = 0, i; keyval_strings_t *map = NULL, *entry = NULL; + upsdebugx(2, "%s: %s", __func__, device + ? (device->type < TYPE_END ? nutscan_device_type_string[device->type] : "") + : ""); + if (device == NULL) { return; } @@ -299,6 +314,10 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) void nutscan_display_sanity_check(nutscan_device_t * device) { + upsdebugx(2, "%s: %s", __func__, device + ? (device->type < TYPE_END ? nutscan_device_type_string[device->type] : "") + : ""); + /* Extend the list later as more sanity-checking appears */ nutscan_display_sanity_check_serial(device); } From a40db655cf1eb97059f04b74eba49baaa76016e2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 23:52:09 +0100 Subject: [PATCH 0356/1232] tools/nut-scanner/nutscan-display.c: nutscan_display_sanity_check_serial(): trace progress through logic [#1810] --- tools/nut-scanner/nutscan-display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index fdadd37f81..e30d13e987 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -207,6 +207,9 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) return; } + upsdebugx(3, "%s: checking serial numbers for %" PRIuSIZE " device configuration(s)", + __func__, listlen); + do { /* Look for serial option in current device */ opt = current_dev->opt; @@ -227,6 +230,9 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) if (entry) { /* Got a hit => append value */ + upsdebugx(3, "%s: duplicate entry for serial '%s'", + __func__, keytmp); + /* TODO: If changing from preallocated LARGEBUF to * dynamic allocation, malloc data for larger "val". */ @@ -234,6 +240,9 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) ",nutdev%i", nutdev_num); } else { /* No hit => new key */ + upsdebugx(3, "%s: new entry for serial '%s'", + __func__, keytmp); + /* TODO: If changing from preallocated LARGEBUF to * dynamic allocation, malloc data for new "entry" * and its key/val fields. @@ -244,6 +253,8 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) if (count != i || count > listlen) { /* Should never get here, but just in case... */ fprintf(stderr, "%s: Loop overflow, skipped\n", __func__); + upsdebugx(3, "%s: count=%" PRIuSIZE " i=%" PRIuSIZE " listlen%" PRIuSIZE, + __func__, count, i, listlen); goto exit; } From fb1856d46eceb7b22fcd6a12a18e37174d63d1f4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 23:52:30 +0100 Subject: [PATCH 0357/1232] tools/nut-scanner/nutscan-display.c: nutscan_display_sanity_check_serial(): if not null, one device entry exists [#1810] --- tools/nut-scanner/nutscan-display.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index e30d13e987..95ed0c98f3 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -178,6 +178,9 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) return; } + /* At least one entry exists... */ + listlen++; + /* Find end of the list */ while (current_dev->next != NULL) { current_dev = current_dev->next; @@ -189,11 +192,6 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) listlen++; } - /* Empty? No bogus data or conflicts at least... */ - if (!listlen) { - return; - } - /* Process each device: * Build a map of "serial"=>"nutdevX[,...,nutdevZ]" * and warn if there are bogus "serial" keys or if From 7304fc54390245a987e7c9be82598ab3c3a65255 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Jan 2023 23:53:00 +0100 Subject: [PATCH 0358/1232] tools/nut-scanner/nutscan-display.c: nutscan_display_sanity_check_serial(): fix failsafe condition [#1810] --- tools/nut-scanner/nutscan-display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index 95ed0c98f3..b4e562c2ef 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -248,7 +248,7 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) entry = &(map[i]); count++; - if (count != i || count > listlen) { + if (count != (i + 1) || count > listlen) { /* Should never get here, but just in case... */ fprintf(stderr, "%s: Loop overflow, skipped\n", __func__); upsdebugx(3, "%s: count=%" PRIuSIZE " i=%" PRIuSIZE " listlen%" PRIuSIZE, From 10e0d0b093d69bf632f2a0a85d0809f82906c65a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 00:01:24 +0100 Subject: [PATCH 0359/1232] tools/nut-scanner/nutscan-display.c: weave nutdevX numbering for different scan types when generating ups.conf with sanity-check warnings with a global var [#1810] --- tools/nut-scanner/nutscan-display.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index b4e562c2ef..9cfa2716ec 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -39,6 +39,8 @@ static char * nutscan_device_type_string[TYPE_END] = { "EATON_SERIAL" }; +static int last_nutdev_num = 0; + void nutscan_display_ups_conf_with_sanity_check(nutscan_device_t * device) { upsdebugx(2, "%s: %s", __func__, device @@ -91,6 +93,8 @@ void nutscan_display_ups_conf(nutscan_device_t * device) current_dev = current_dev->next; } while (current_dev != NULL); + + last_nutdev_num = nutdev_num; } void nutscan_display_parsable(nutscan_device_t * device) @@ -164,9 +168,19 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) * Also note that not all devices may have/report * a serial at all (option will be missing). */ + /* FIXME: Currently this is normally called as part + * of nutscan_display_ups_conf_with_sanity_check() + * and nut-scanner goes over each type separately. + * So with current approach it will not see "issues" + * with multiple data paths (e.g. USB and SNMP) to + * same device. + */ nutscan_device_t * current_dev = device; nutscan_options_t * opt; - int nutdev_num = 1; + /* Keep numbering consistent with global entry naming. + * Note its last value is after loop, so "real + 1". + */ + int nutdev_num = last_nutdev_num - 1; size_t listlen = 0, count = 0, i; keyval_strings_t *map = NULL, *entry = NULL; From f6fa8b934dc52e3223f60fb24cc8b783aa5a5507 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 12:12:12 +0100 Subject: [PATCH 0360/1232] tests/NIT/nit.sh: add rudimentary nut-scanner tests --- tests/NIT/nit.sh | 74 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 8b8c6a38d9..19c7ff892e 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -22,7 +22,7 @@ # ksh, busybox sh...) # # Copyright -# 2022 Jim Klimov +# 2022-2023 Jim Klimov # # License: GPLv2+ @@ -1106,8 +1106,71 @@ testcases_sandbox_cppnit() { testcase_sandbox_cppnit_simple_admin } +#################################### + +isTestableNutScanner() { + # We optionally make and here can run nut-scanner (as NUT client) + # tests, which tangentially tests the C client library: + if [ x"${TOP_BUILDDIR}" = x ] \ + || [ ! -x "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" ] \ + ; then + log_warn "SKIP: ${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner: Not found" + return 1 + fi + return 0 +} + +testcase_sandbox_nutscanner_list() { + isTestableNutScanner || return 0 + + log_separator + log_info "Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" + + # NOTE: Currently mask mode is IPv4 only + { OUT="`"${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -m 127.0.0.1/32 -O -p "${NUT_PORT}"`" \ + || OUT="`"${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -s localhost -O -p "${NUT_PORT}"`" ; } \ + && [ -n "$OUT" ] \ + || OUT="" + + # Note: the reported "driver" string is not too helpful as a "nutclient". + # In practice this could be a "dummy-ups" repeater or "clone" driver, + # or some of the config elements needed for upsmon (lacking creds/role) + if ( + test -n "$OUT" \ + && echo "$OUT" | grep -E '^\[nutdev1\]$' \ + && echo "$OUT" | grep 'port = "dummy@' \ + || return + + if [ x"${TOP_SRCDIR}" = x ]; then + echo "Note: only testing one dummy device" >&2 + else + echo "$OUT" | grep -E '^\[nutdev2\]$' \ + && echo "$OUT" | grep 'port = "UPS1@' \ + && echo "$OUT" | grep -E '^\[nutdev3\]$' \ + && echo "$OUT" | grep 'port = "UPS2@' \ + || return + fi + ) ; then + log_info "OK, nut-scanner found all expected devices" + PASSED="`expr $PASSED + 1`" + else + log_error "nut-scanner complained, check above" + FAILED="`expr $FAILED + 1`" + FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_nutscanner_list" + fi +} + +testcases_sandbox_nutscanner() { + isTestableNutScanner || return 0 + testcase_sandbox_nutscanner_list +} + +#################################### + # TODO: Some upsmon tests? +#################################### + testgroup_sandbox() { testcase_sandbox_start_drivers_after_upsd testcase_sandbox_upsc_query_model @@ -1115,6 +1178,7 @@ testgroup_sandbox() { testcase_sandbox_upsc_query_timer testcases_sandbox_python testcases_sandbox_cppnit + testcases_sandbox_nutscanner sandbox_forget_configs } @@ -1140,11 +1204,19 @@ testgroup_sandbox_cppnit_simple_admin() { sandbox_forget_configs } +testgroup_sandbox_nutscanner() { + # Arrange for quick test iterations + testcase_sandbox_start_drivers_after_upsd + testcases_sandbox_nutscanner + sandbox_forget_configs +} + ################################################################ case "${NIT_CASE}" in cppnit) testgroup_sandbox_cppnit ;; python) testgroup_sandbox_python ;; + nutscanner|nut-scanner) testgroup_sandbox_nutscanner ;; testcase_*|testgroup_*|testcases_*|testgroups_*) log_warn "========================================================" log_warn "You asked to run just a specific testcase* or testgroup*" From 511e38bbbd2cdf39114e128fabccaf7e661f321c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 12:23:36 +0100 Subject: [PATCH 0361/1232] tools/nut-scanner/scan_avahi.c: when bailing out of Avahi scan, do so comprehensibly for readers of error messages --- tools/nut-scanner/scan_avahi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 7bf7fa5a0a..63730a0a58 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -519,7 +519,7 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout) /* Allocate main loop object */ if (!(simple_poll = (*nut_avahi_simple_poll_new)())) { - fprintf(stderr, "Failed to create simple poll object.\n"); + fprintf(stderr, "Failed to create Avahi simple poll object.\n"); goto fail; } @@ -541,7 +541,7 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout) /* Check wether creating the client object succeeded */ if (!client) { fprintf(stderr, - "Failed to create client: %s\n", + "Failed to create Avahi client: %s\n", (*nut_avahi_strerror)(error)); goto fail; } @@ -560,7 +560,7 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout) # pragma GCC diagnostic pop #endif fprintf(stderr, - "Failed to create service browser: %s\n", + "Failed to create Avahi service browser: %s\n", (*nut_avahi_strerror)((*nut_avahi_client_errno)(client))); goto fail; } From b5f7fb1fdb25ef1a62d00184099f7b118ac711fb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 16 Nov 2022 16:06:06 +0100 Subject: [PATCH 0362/1232] m4/nut_report_feature.m4: report configure invocation args --- configure.ac | 6 ++++++ m4/nut_report_feature.m4 | 1 + 2 files changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index 4615a96e2c..61f8e44c7e 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,12 @@ dnl NUT version number is defined here, with a Git suffixed macro like dnl NUT_VERSION_MACRO "2.7.4-2838-gdfc3ac08" dnl in include/nut_version.h (generated by make) AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) + +dnl Keep track of command-line options passed to this script: +CONFIG_FLAGS="$*" +AC_DEFINE_UNQUOTED([CONFIG_FLAGS],["${CONFIG_FLAGS}"],[Flags passed to configure script]) +AC_SUBST(CONFIG_FLAGS) + AC_CONFIG_AUX_DIR([.]) AC_CONFIG_SRCDIR(server/upsd.c) AC_CONFIG_MACRO_DIR([m4]) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 87a565722f..dbe4455a29 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -132,6 +132,7 @@ AC_DEFUN([NUT_REPORT_COMPILERS], printf '* CXXFLAGS\t: %s\n' "$CXXFLAGS" printf '* CPP \t: %s\n' "$CPP" printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" + printf '* CONFIG_FLAGS\t: %s\n' "$CONFIG_FLAGS" ) > config.nut_report_feature.log.9 ac_clean_files="${ac_clean_files} config.nut_report_feature.log.9" ]) From b61f74e3112f83a83562bcceefd1b2285d2687c4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 13:42:43 +0100 Subject: [PATCH 0363/1232] lib/libupsclient-config.in: double-quote shell expansions --- lib/libupsclient-config.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libupsclient-config.in b/lib/libupsclient-config.in index 2a59f70238..73960ddfb6 100644 --- a/lib/libupsclient-config.in +++ b/lib/libupsclient-config.in @@ -8,8 +8,8 @@ # **********************************************************# Version="@PACKAGE_VERSION@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" Libs="-L@libdir@ -lupsclient @LIBSSL_LIBS@" Cflags="-I@includedir@ @LIBSSL_CFLAGS@" @@ -22,7 +22,7 @@ case "$1" in echo "$Libs" ;; --version) - echo $Version + echo "$Version" ;; *) echo "Usage: libupsclient-config {--cflags|--libs|--version}" From a3ecb175978548be0f5df07ae7055ddd1ec37171 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 13:43:04 +0100 Subject: [PATCH 0364/1232] lib/libupsclient-config.in: report CONFIG_FLAGS --- lib/libupsclient-config.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/libupsclient-config.in b/lib/libupsclient-config.in index 73960ddfb6..97cd6d0749 100644 --- a/lib/libupsclient-config.in +++ b/lib/libupsclient-config.in @@ -12,6 +12,7 @@ prefix="@prefix@" exec_prefix="@exec_prefix@" Libs="-L@libdir@ -lupsclient @LIBSSL_LIBS@" Cflags="-I@includedir@ @LIBSSL_CFLAGS@" +ConfigFlags="@CONFIG_FLAGS@" case "$1" in @@ -24,8 +25,11 @@ case "$1" in --version) echo "$Version" ;; + --config_flags|--config-flags) + echo "$ConfigFlags" + ;; *) - echo "Usage: libupsclient-config {--cflags|--libs|--version}" + echo "Usage: libupsclient-config {--cflags|--libs|--version|--config_flags}" exit 1 esac From 8089ea08cb439fa5a451a344824d68538274f4e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 14:22:41 +0100 Subject: [PATCH 0365/1232] configure.ac: lib/libupsclient-config is a SCRIPTFILE --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 61f8e44c7e..ad48db5fca 100644 --- a/configure.ac +++ b/configure.ac @@ -3854,7 +3854,6 @@ AC_CONFIG_FILES([ docs/man/Makefile drivers/Makefile include/Makefile - lib/libupsclient-config lib/libupsclient.pc lib/libnutclient.pc lib/libnutclientstub.pc @@ -3908,6 +3907,7 @@ AC_CONFIG_FILES([ AC_MSG_NOTICE([Generating templated script files that should be marked executable]) m4_foreach_w([SCRIPTFILE], [ + lib/libupsclient-config scripts/Aix/nut.init scripts/HP-UX/postinstall scripts/RedHat/upsd From a1d4ffd4118256c3b1d27c614e0a026b21fd9cfa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 14:13:12 +0100 Subject: [PATCH 0366/1232] NUT programs should report CONFIG_FLAGS for help/version requests with debug enabled Related-to: #1789 --- clients/upsc.c | 6 ++++++ clients/upscmd.c | 6 ++++++ clients/upslog.c | 5 +++++ clients/upsmon.c | 5 +++++ clients/upsrw.c | 5 +++++ docs/configure.txt | 13 +++++++++++++ drivers/main.c | 7 ++++++- server/upsd.c | 8 +++++++- tools/nut-scanner/nut-scanner.c | 8 ++++++++ 9 files changed, 61 insertions(+), 2 deletions(-) diff --git a/clients/upsc.c b/clients/upsc.c index 675c4d92b7..6181e6bfed 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -56,6 +56,9 @@ static void usage(const char *prog) printf("\nThird form (lists clients connected to a device):\n"); printf(" -c - lists each client connected on , one per line.\n"); printf(" - upsd server, [@[:]] form\n"); + + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); } static void printvar(const char *var) @@ -232,6 +235,9 @@ int main(int argc, char **argv) break; case 'V': + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); #ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_SUCCESS); /* Should not get here in practice, but compiler is afraid we can fall through */ diff --git a/clients/upscmd.c b/clients/upscmd.c index 9d8c35c4cf..be24a6e2c2 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -64,6 +64,9 @@ static void usage(const char *prog) printf(" UPS identifier - [@[:]]\n"); printf(" Valid instant command - test.panel.start, etc.\n"); printf(" [] Additional data for command - number of seconds, etc.\n"); + + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); } static void print_cmd(char *cmdname) @@ -309,6 +312,9 @@ int main(int argc, char **argv) break; case 'V': + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); #ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_SUCCESS); /* Should not get here in practice, but compiler is afraid we can fall through */ diff --git a/clients/upslog.c b/clients/upslog.c index 191aedf390..ae151c83c0 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -176,6 +176,9 @@ static void help(const char *prog) printf("\n"); printf("See the upslog(8) man page for more information.\n"); + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + exit(EXIT_SUCCESS); } @@ -501,6 +504,8 @@ int main(int argc, char **argv) break; case 'V': + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); exit(EXIT_SUCCESS); case 'p': diff --git a/clients/upsmon.c b/clients/upsmon.c index 29f0fe9be5..b7c07f6e00 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2182,6 +2182,9 @@ static void help(const char *arg_progname) printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + exit(EXIT_SUCCESS); } @@ -2498,6 +2501,8 @@ int main(int argc, char *argv[]) break; case 'V': /* just show the banner */ + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); exit(EXIT_SUCCESS); case '4': opt_af = AF_INET; diff --git a/clients/upsrw.c b/clients/upsrw.c index aadc2ff866..0148baed20 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -65,6 +65,9 @@ static void usage(const char *prog) printf(" UPS identifier - [@[:]]\n"); printf("\n"); printf("Call without -s to show all possible read/write variables (same as -l).\n"); + + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); } static void clean_exit(void) @@ -666,6 +669,8 @@ int main(int argc, char **argv) break; case 'V': printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); exit(EXIT_SUCCESS); case 'h': default: diff --git a/docs/configure.txt b/docs/configure.txt index 20441a2545..78bee4021b 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -28,6 +28,19 @@ There are a few options reviewed below that can be given to `configure` script to tweak your compilations. See also `./configure --help` for a current and complete listing for the current version of the codebase. +NUT tracks `configure` options used during build, so you can view them +to produce a replacement by asking NUT programs for `--help` or for +`--version` with debugging enabled (first), e.g.: + +---- +:; upsd -DV +Network UPS Tools upsd 2.8.0.1 + 0.000000 [D1] Network UPS Tools version 2.8.0.1 configured with flags: --with-all=auto --with-doc=skip ... +---- + +A more industrial approach is to use `lib/libupsclient-config --config-flags` +where supported. + In-place replacement defaults ----------------------------- diff --git a/drivers/main.c b/drivers/main.c index fadb20d383..a408d7c2c1 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -134,6 +134,9 @@ static void help_msg(void) { vartab_t *tmp; + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + printf("\nusage: %s (-a |-s ) [OPTIONS]\n", progname); printf(" -a - autoconfig using ups.conf section \n"); @@ -827,7 +830,9 @@ int main(int argc, char **argv) group_from_cmdline = 1; break; case 'V': - /* already printed the banner, so exit */ + /* already printed the banner for program name */ + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); exit(EXIT_SUCCESS); case 'x': splitxarg(optarg); diff --git a/server/upsd.c b/server/upsd.c index 1a87b55d61..135febcc0e 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1507,6 +1507,9 @@ static void help(const char *arg_progname) printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + exit(EXIT_SUCCESS); } @@ -1632,7 +1635,10 @@ int main(int argc, char **argv) break; case 'V': - /* do nothing - we already printed the banner */ + /* Note - we already printed the banner for program name */ + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + exit(EXIT_SUCCESS); case 'c': diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 05e28f7d00..43b2477c89 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -177,6 +177,10 @@ static void show_usage() { /* NOTE: This code uses `nutscan_avail_*` global vars from nutscan-init.c */ puts("nut-scanner : utility for detection of available power devices.\n"); + + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + NUT_VERSION_MACRO, CONFIG_FLAGS); + puts("OPTIONS:"); printf(" -C, --complete_scan: Scan all available devices except serial ports (default).\n"); if (nutscan_avail_usb) { @@ -648,6 +652,10 @@ int main(int argc, char *argv[]) break; case 'V': printf("Network UPS Tools - %s\n", NUT_VERSION_MACRO); + + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + NUT_VERSION_MACRO, CONFIG_FLAGS); + exit(EXIT_SUCCESS); case 'a': printf("OLDNUT\n"); From 7070ef58012341ce66c80f51d732d9102a2ff3fc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 14:20:42 +0100 Subject: [PATCH 0367/1232] drivers/main.c: report CONFIG_FLAGS always when debugging [#1789] --- drivers/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index a408d7c2c1..362bac6103 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -861,6 +861,14 @@ int main(int argc, char **argv) } } /* else: default remains `background_flag==-1` where nonzero is true */ + /* Since debug mode dumps from drivers are often posted to mailing list + * or issue tracker, as well as viewed locally, it can help to know the + * build options involved when troubleshooting (especially when needed + * to walk through building a PR branch with candidate fix for an issue). + */ + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); + argc -= optind; argv += optind; From 285e0065cd5e40f73b84e437b913772b08d76e67 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 14:53:28 +0100 Subject: [PATCH 0368/1232] configure.ac: consult CONFIG_FLAGS_DEPLOYED and CONFIG_FLAGS when --enable-inplace-runtime mode is used --- configure.ac | 30 ++++++++++++++++++++++++++++++ docs/configure.txt | 6 +++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ad48db5fca..a022c8a057 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,36 @@ NUT_ARG_ENABLE([inplace-runtime], [Request configure option defaults for runtime user/group/confpath based on currently installed NUT (to extent these can be detected)], [no]) +AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ + AC_MSG_CHECKING([for CONFIG_FLAGS of an already deployed NUT build (if it reports those)]) + + dnl If existing NUT installation reports its build options, re-run this + dnl script with those flags (overridden by any options passed currently): + conftemp="${sbindir}" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + SBINDIR="${conftemp}" + + CONFIG_FLAGS_DEPLOYED="" + dnl TODO: Similar query can be done for BINDIR tools + dnl and for libupsclient-config if deployed locally + AC_MSG_CHECKING([${SBINDIR}/upsd]) + AS_IF([test -x "${SBINDIR}/upsd"], [ + CONFIG_FLAGS_DEPLOYED="`"${SBINDIR}/upsd" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*configured with flags: *,,'`" \ + && test x"${CONFIG_FLAGS_DEPLOYED}" != x \ + || CONFIG_FLAGS_DEPLOYED="" + ]) + + AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ + AC_MSG_RESULT([${CONFIG_FLAGS_DEPLOYED}]) + AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) + dnl For multiply-specified flags with conflicting values, last mention wins: + exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime + ],[ + AC_MSG_RESULT([not reported]) + ]) +]) + dnl Defaults for respective configure options below dnl Note these defaults may change further below depending on OS and dnl certain other configure options (e.g. "in-place replacement") diff --git a/docs/configure.txt b/docs/configure.txt index 78bee4021b..138bae9142 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -55,12 +55,16 @@ filesystem access permissions and configuration file locations. Tries to detect and pre-set `configure` defaults for run-time settings (which you can still override if needed, but no longer *must* specify -explicitly to be on same page as the existing setup): +explicitly to be on same page as the existing setup), e.g.: * --sysconfdir * --with-user * --with-group +If the installed NUT version supports reporting of `CONFIG_FLAGS` used +during its build, the `configure` script will try to take those values +into account when running in this mode. + Driver selection ---------------- From 0539bc39acaf7969a850121df0eba981d06d70bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 15:32:15 +0100 Subject: [PATCH 0369/1232] tests/NIT/nit.sh: testcase_sandbox_nutscanner_list(): excuse lack of libupsclient.so/dll in path --- tests/NIT/nit.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 19c7ff892e..d1739a01bb 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1127,36 +1127,38 @@ testcase_sandbox_nutscanner_list() { log_info "Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" # NOTE: Currently mask mode is IPv4 only - { OUT="`"${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -m 127.0.0.1/32 -O -p "${NUT_PORT}"`" \ - || OUT="`"${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -s localhost -O -p "${NUT_PORT}"`" ; } \ - && [ -n "$OUT" ] \ - || OUT="" + runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -m 127.0.0.1/32 -O -p "${NUT_PORT}" \ + || runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -s localhost -O -p "${NUT_PORT}" # Note: the reported "driver" string is not too helpful as a "nutclient". # In practice this could be a "dummy-ups" repeater or "clone" driver, # or some of the config elements needed for upsmon (lacking creds/role) if ( - test -n "$OUT" \ - && echo "$OUT" | grep -E '^\[nutdev1\]$' \ - && echo "$OUT" | grep 'port = "dummy@' \ + test -n "$CMDOUT" \ + && echo "$CMDOUT" | grep -E '^\[nutdev1\]$' \ + && echo "$CMDOUT" | grep 'port = "dummy@' \ || return if [ x"${TOP_SRCDIR}" = x ]; then echo "Note: only testing one dummy device" >&2 else - echo "$OUT" | grep -E '^\[nutdev2\]$' \ - && echo "$OUT" | grep 'port = "UPS1@' \ - && echo "$OUT" | grep -E '^\[nutdev3\]$' \ - && echo "$OUT" | grep 'port = "UPS2@' \ + echo "$CMDOUT" | grep -E '^\[nutdev2\]$' \ + && echo "$CMDOUT" | grep 'port = "UPS1@' \ + && echo "$CMDOUT" | grep -E '^\[nutdev3\]$' \ + && echo "$CMDOUT" | grep 'port = "UPS2@' \ || return fi ) ; then log_info "OK, nut-scanner found all expected devices" PASSED="`expr $PASSED + 1`" else - log_error "nut-scanner complained, check above" - FAILED="`expr $FAILED + 1`" - FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_nutscanner_list" + if ( echo "$CMDERR" | grep -E "Cannot load NUT library.*libupsclient.*The specified module could not be found.*NUT search disabled" ) ; then + log_warn "SKIP: ${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner: $CMDERR" + else + log_error "nut-scanner complained or did not return all expected data, check above" + FAILED="`expr $FAILED + 1`" + FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_nutscanner_list" + fi fi } From 24644603c12408a3a3307e2d9b91aa867b0055dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 15:45:09 +0100 Subject: [PATCH 0370/1232] configure.ac: log the CLI options for restarted run when nut_enable_inplace_runtime --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index a022c8a057..18c4af291e 100644 --- a/configure.ac +++ b/configure.ac @@ -170,6 +170,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AC_MSG_RESULT([${CONFIG_FLAGS_DEPLOYED}]) AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) dnl For multiply-specified flags with conflicting values, last mention wins: + AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime ],[ AC_MSG_RESULT([not reported]) From b0ea5f170f1e689aafcab17591142d5d966a0a4f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Jan 2023 16:01:43 +0100 Subject: [PATCH 0371/1232] configure.ac: fix support for CONFIG_FLAGS with spaces --- configure.ac | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 18c4af291e..9d5d955d35 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,19 @@ dnl in include/nut_version.h (generated by make) AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) dnl Keep track of command-line options passed to this script: -CONFIG_FLAGS="$*" +CONFIG_FLAGS="" +dnl Keep each token quoted, in case spaces or other special chars crawl in: +for F in "$@" ; do + case "$F" in + *=*" "*) NF="`echo "$F" | sed "s,=,=',"`""'" && F="$NF" ;; + esac + + test -z "${CONFIG_FLAGS}" \ + && CONFIG_FLAGS="$F" \ + || CONFIG_FLAGS="${CONFIG_FLAGS} $F" +done +unset F +unset NF AC_DEFINE_UNQUOTED([CONFIG_FLAGS],["${CONFIG_FLAGS}"],[Flags passed to configure script]) AC_SUBST(CONFIG_FLAGS) @@ -171,7 +183,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) dnl For multiply-specified flags with conflicting values, last mention wins: AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) - exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime + eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime ],[ AC_MSG_RESULT([not reported]) ]) From 41433f99cedd8757e05adc21f462986fa2fe2e2e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 00:37:45 +0000 Subject: [PATCH 0372/1232] configure.ac: CONFIG_FLAGS: older ksh dislikes doublequotes inside backticks, all doublequoted outside => use $(...) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9d5d955d35..a44fc30aad 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ CONFIG_FLAGS="" dnl Keep each token quoted, in case spaces or other special chars crawl in: for F in "$@" ; do case "$F" in - *=*" "*) NF="`echo "$F" | sed "s,=,=',"`""'" && F="$NF" ;; + *=*" "*) NF="$(echo "$F" | sed "s,=,=',")""'" && F="$NF" ;; esac test -z "${CONFIG_FLAGS}" \ From a050851b271aed21aa03de2033e3ac183b09a70a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 09:43:00 +0100 Subject: [PATCH 0373/1232] tests/NIT/nit.sh: simplify bail-out pattern for nut-scanner to match on more OSes --- 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 d1739a01bb..ff50e29067 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1152,7 +1152,7 @@ testcase_sandbox_nutscanner_list() { log_info "OK, nut-scanner found all expected devices" PASSED="`expr $PASSED + 1`" else - if ( echo "$CMDERR" | grep -E "Cannot load NUT library.*libupsclient.*The specified module could not be found.*NUT search disabled" ) ; then + if ( echo "$CMDERR" | grep -E "Cannot load NUT library.*libupsclient.*found.*NUT search disabled" ) ; then log_warn "SKIP: ${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner: $CMDERR" else log_error "nut-scanner complained or did not return all expected data, check above" From 8d25a53a927de64e970db4511bd2ef15e6bd6478 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:25:56 +0100 Subject: [PATCH 0374/1232] tests/NIT/nit.sh: fix LD_LIBRARY_PATH for testcase_sandbox_nutscanner_list() --- tests/NIT/nit.sh | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index ff50e29067..e392845e37 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -189,9 +189,10 @@ case "${SRCDIR}" in *) log_info "Script source directory '${SRCDIR}' is not a .../tests/NIT" ;; esac -# No fuss about LD_LIBRARY_PATH: for binaries that need it, -# PATH entries below would contain libtool wrapper scripts; -# for other builds we use system default or caller's env. +# No fuss about LD_LIBRARY_PATH: for most of the (client) binaries that +# need it, the PATH entries below would contain libtool wrapper scripts; +# for other builds we use system default or caller's env. One exception +# so far is nut-scanner that needs to know where libupsclient.so is... PATH_ADD="${BUILDDIR}" if [ x"${SRCDIR}" != x"${BUILDDIR}" ]; then PATH_ADD="${PATH_ADD}:${SRCDIR}" @@ -211,6 +212,20 @@ unset PATH_ADD log_debug "Using PATH='$PATH'" +LD_LIBRARY_PATH_ORIG="${LD_LIBRARY_PATH-}" +LD_LIBRARY_PATH_CLIENT="" +if [ x"${TOP_BUILDDIR}" != x ]; then + LD_LIBRARY_PATH_CLIENT="${TOP_BUILDDIR}/clients:${TOP_BUILDDIR}/clients/.libs" +fi + +if [ x"${LD_LIBRARY_PATH_CLIENT}" != x ]; then + if [ -n "${LD_LIBRARY_PATH_ORIG-}" ]; then + LD_LIBRARY_PATH_CLIENT="${LD_LIBRARY_PATH_CLIENT}:${LD_LIBRARY_PATH_ORIG}" + fi +else + LD_LIBRARY_PATH_CLIENT="${LD_LIBRARY_PATH_ORIG}" +fi + for PROG in upsd upsc dummy-ups upsmon ; do (command -v ${PROG}) || die "Useless setup: ${PROG} not found in PATH: ${PATH}" done @@ -1125,11 +1140,19 @@ testcase_sandbox_nutscanner_list() { log_separator log_info "Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" + log_info "Preparing LD_LIBRARY_PATH='${LD_LIBRARY_PATH_CLIENT}'" + + # Note: for some reason `LD_LIBRARY_PATH=... runcmd ...` loses it :\ + LD_LIBRARY_PATH="${LD_LIBRARY_PATH_CLIENT}" + export LD_LIBRARY_PATH # NOTE: Currently mask mode is IPv4 only runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -m 127.0.0.1/32 -O -p "${NUT_PORT}" \ || runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -s localhost -O -p "${NUT_PORT}" + LD_LIBRARY_PATH="${LD_LIBRARY_PATH_ORIG}" + export LD_LIBRARY_PATH + # Note: the reported "driver" string is not too helpful as a "nutclient". # In practice this could be a "dummy-ups" repeater or "clone" driver, # or some of the config elements needed for upsmon (lacking creds/role) From dd21b1a4a96a6bc137a5f3587763fc203ed61a38 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:36:57 +0100 Subject: [PATCH 0375/1232] tools/nut-scanner/scan_nut.c: use uint16_t port to align with upsclient.c [#1815] --- tools/nut-scanner/scan_nut.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index dabe9812f4..3114c646ff 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -33,8 +33,8 @@ static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; -static int (*nut_upscli_splitaddr)(const char *buf, char **hostname, int *port); -static int (*nut_upscli_tryconnect)(UPSCONN_t *ups, const char *host, int port, +static int (*nut_upscli_splitaddr)(const char *buf, char **hostname, uint16_t *port); +static int (*nut_upscli_tryconnect)(UPSCONN_t *ups, const char *host, uint16_t port, int flags, struct timeval * timeout); static int (*nut_upscli_list_start)(UPSCONN_t *ups, size_t numq, const char **query); @@ -137,7 +137,7 @@ static void * list_nut_devices(void * arg) struct scan_nut_arg * nut_arg = (struct scan_nut_arg*)arg; char *target_hostname = nut_arg->hostname; struct timeval tv; - int port; + uint16_t port; size_t numq, numa; const char *query[4]; char **answer; From 2e767c929edb1adc9f90cc7b2c491b0d71944266 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:37:28 +0100 Subject: [PATCH 0376/1232] tools/nut-scanner/scan_nut.c: suffix non-standard port numbers to "port" in config [#1815] --- tools/nut-scanner/scan_nut.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index 3114c646ff..2cb0aab722 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -193,11 +193,30 @@ static void * list_nut_devices(void * arg) dev->driver = strdup("nutclient"); /* +1+1 is for '@' character and terminating 0 */ buf_size = strlen(answer[1]) + strlen(hostname) + 1 + 1; +#if (defined PORT) && (PORT > 0) + if (port != PORT) { +#else + if (port != 3493) { +#endif + /* colon and up to 5 digits */ + buf_size += 6; + } + dev->port = malloc(buf_size); if (dev->port) { - snprintf(dev->port, buf_size, "%s@%s", answer[1], - hostname); +#if (defined PORT) && (PORT > 0) + if (port != PORT) { +#else + if (port != 3493) { +#endif + snprintf(dev->port, buf_size, "%s@%s:%" PRIu16, + answer[1], hostname, port); + } else { + /* Standard port, not suffixed */ + snprintf(dev->port, buf_size, "%s@%s", + answer[1], hostname); + } #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif From 2f34c236389077471eb59b721847d72484d3dd6f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:43:14 +0100 Subject: [PATCH 0377/1232] tools/nut-scanner/scan_nut.c: comment about "nutclient" driver value --- tools/nut-scanner/scan_nut.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index 2cb0aab722..1f272cb36e 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -190,6 +190,8 @@ static void * list_nut_devices(void * arg) * - for upsmon.conf or ups.conf (using dummy-ups)? */ dev = nutscan_new_device(); dev->type = TYPE_NUT; + /* NOTE: There is no driver by such name, in practice it could + * be a dummy-ups relay, a clone driver, or part of upsmon config */ dev->driver = strdup("nutclient"); /* +1+1 is for '@' character and terminating 0 */ buf_size = strlen(answer[1]) + strlen(hostname) + 1 + 1; From 0716d27273af6abafba6e86b4c977bfc7b839015 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:56:32 +0100 Subject: [PATCH 0378/1232] tests/NIT/nit.sh: verify that port number is suffixed by nut-scanner when needed [#1815] --- tests/NIT/nit.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index e392845e37..61349f23fe 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1162,6 +1162,13 @@ testcase_sandbox_nutscanner_list() { && echo "$CMDOUT" | grep 'port = "dummy@' \ || return + if [ "${NUT_PORT}" = 3493 ] || [ x"$NUT_PORT" = x ]; then + echo "Note: not testing for suffixed port number" >&2 + else + echo "$CMDOUT" | grep -E 'dummy@.*'":${NUT_PORT}" \ + || return + fi + if [ x"${TOP_SRCDIR}" = x ]; then echo "Note: only testing one dummy device" >&2 else From 6c2f11520adb6692d323923188b24c8e0019f164 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:59:03 +0100 Subject: [PATCH 0379/1232] tools/nut-scanner/scan_avahi.c: comments similar to scan_nut.c --- tools/nut-scanner/scan_avahi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 63730a0a58..18344709b1 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -264,6 +264,8 @@ static void update_device(const char * host_name, const char *ip, uint16_t port, device_found = 1; dev = nutscan_new_device(); dev->type = TYPE_NUT; + /* NOTE: There is no driver by such name, in practice it could + * be a dummy-ups relay, a clone driver, or part of upsmon config */ dev->driver = strdup("nutclient"); if (proto == AVAHI_PROTO_INET) { nutscan_add_option_to_device(dev, "desc", "IPv4"); @@ -282,7 +284,7 @@ static void update_device(const char * host_name, const char *ip, uint16_t port, 5 + 1 + 1 + 1; dev->port = malloc(buf_size); if (dev->port) { - snprintf(dev->port, buf_size, "%s@%s:%u", + snprintf(dev->port, buf_size, "%s@%s:%" PRIu16, device, host_name, port); } } From 53a57150b929a66a07b7f54237c5f500d65d651b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 10:59:55 +0100 Subject: [PATCH 0380/1232] tools/nut-scanner/scan_nut.c: simplify check for "port" similar to scan_avahi.c [#1815] --- tools/nut-scanner/scan_nut.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index 1f272cb36e..7b2e5f1a1a 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -195,11 +195,7 @@ static void * list_nut_devices(void * arg) dev->driver = strdup("nutclient"); /* +1+1 is for '@' character and terminating 0 */ buf_size = strlen(answer[1]) + strlen(hostname) + 1 + 1; -#if (defined PORT) && (PORT > 0) if (port != PORT) { -#else - if (port != 3493) { -#endif /* colon and up to 5 digits */ buf_size += 6; } @@ -207,11 +203,7 @@ static void * list_nut_devices(void * arg) dev->port = malloc(buf_size); if (dev->port) { -#if (defined PORT) && (PORT > 0) if (port != PORT) { -#else - if (port != 3493) { -#endif snprintf(dev->port, buf_size, "%s@%s:%" PRIu16, answer[1], hostname, port); } else { From 12442880bdcb40d81217f6aefee44000a1b2bdfc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Jan 2023 18:07:17 +0100 Subject: [PATCH 0381/1232] nut-monitor.appdata.xml: add launchable=nut-monitor.desktop Inspired by https://salsa.debian.org/debian/nut/-/blob/a009ca10a327d7db383f5d7726091050ceb4d60f/debian/patches/appdata-launchable.patch from @bigon but adjusted for general version-agnostic dispatcher (py2 or py3, whatever is installed for this end-user deployment) --- scripts/python/app/nut-monitor.appdata.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/python/app/nut-monitor.appdata.xml b/scripts/python/app/nut-monitor.appdata.xml index 0a06674236..7222dafce9 100644 --- a/scripts/python/app/nut-monitor.appdata.xml +++ b/scripts/python/app/nut-monitor.appdata.xml @@ -2,6 +2,7 @@ nut-monitor.desktop + nut-monitor.desktop CC0-1.0 GPL-3.0+ NUT Monitor From f0eee40513b39074ea76e177e94779710f3c436d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Tue, 17 Jan 2023 17:38:40 +0100 Subject: [PATCH 0382/1232] Use libusb_get_device_address(), not libusb_get_port_number() In USB device enumeration, when setting curDevice->Device, use libusb_get_device_address(), not libusb_get_port_number(). While there, rename bus to bus_num to avoid ambiguity. When printf()ing devnum (a size_t), use %zd, which is POSIX, not PRIuSIZE, which is not. --- drivers/libusb1.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 9b571659ff..9b0d4e37a2 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -151,7 +151,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, struct libusb_config_descriptor *conf_desc = NULL; const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; - uint8_t bus, port; + uint8_t bus_num, device_addr; int ret, res; unsigned char buf[20]; const unsigned char *p; @@ -228,39 +228,39 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Device); memset(curDevice, '\0', sizeof(*curDevice)); - bus = libusb_get_bus_number(device); + bus_num = libusb_get_bus_number(device); curDevice->Bus = (char *)malloc(4); if (curDevice->Bus == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - if (bus > 0) { - sprintf(curDevice->Bus, "%03d", bus); + if (bus_num > 0) { + sprintf(curDevice->Bus, "%03d", bus_num); } else { upsdebugx(1, "%s: invalid libusb bus number %i", - __func__, bus); + __func__, bus_num); } - port = libusb_get_port_number(device); + device_addr = libusb_get_device_address(device); curDevice->Device = (char *)malloc(4); if (curDevice->Device == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - if (port > 0) { + if (device_addr > 0) { /* 0 means not available, e.g. lack of platform support */ - sprintf(curDevice->Device, "%03d", port); + sprintf(curDevice->Device, "%03d", device_addr); } else { if (devnum <= 999) { /* Log visibly so users know their number discovered * from `lsusb` or `dmesg` (if any) was ignored */ - upsdebugx(0, "%s: invalid libusb port number %i, " - "falling back to enumeration order counter %" PRIuSIZE, - __func__, port, devnum); + upsdebugx(0, "%s: invalid libusb device address %i, " + "falling back to enumeration order counter %zd", + __func__, device_addr, devnum); sprintf(curDevice->Device, "%03d", (int)devnum); } else { - upsdebugx(1, "%s: invalid libusb port number %i", - __func__, port); + upsdebugx(1, "%s: invalid libusb device address %i", + __func__, device_addr); } } From 5fcde3e183f334d3d32b4b24d9995fe37469e0a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 01:40:24 +0100 Subject: [PATCH 0383/1232] configure.ac: default to automake-"silent" rules for builds --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index a44fc30aad..3c452d1880 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,9 @@ AC_CONFIG_HEADERS([include/config.h]) AC_PREFIX_DEFAULT(/usr/local/ups) AM_INIT_AUTOMAKE([subdir-objects]) +dnl `configure --enable-silent-rules` or `make V=1` for details: +AM_SILENT_RULES([yes]) + dnl we need Autoconf 2.61 or better to enable features of Posix that are extensions to C dnl (and actually 2.64 or better for m4/ax_check_compile_flag.m4 when it is sourced) dnl UPDATE: As tested on CentOS 6, its "autoconf-2.63-5.1.el6.noarch" also suffices. From 9331b542c2aec7b4f3683039b9a6578f6905de34 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 01:41:12 +0100 Subject: [PATCH 0384/1232] ci_build.sh: make verbose builds actually verbose --- ci_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index a556d14571..cbd8c0e392 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -165,7 +165,7 @@ esac [ -n "$GGREP" ] || GGREP=grep [ -n "$MAKE_FLAGS_QUIET" ] || MAKE_FLAGS_QUIET="VERBOSE=0 V=0 -s" -[ -n "$MAKE_FLAGS_VERBOSE" ] || MAKE_FLAGS_VERBOSE="VERBOSE=1 -s" +[ -n "$MAKE_FLAGS_VERBOSE" ] || MAKE_FLAGS_VERBOSE="VERBOSE=1 V=1 -s" # This is where many symlinks like "gcc -> ../bin/ccache" reside # (note: a "-" value requests to NOT use a CI_CCACHE_SYMLINKDIR; From 58726f5f61474dfbcf4005584999f54d740d1d58 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 01:41:36 +0100 Subject: [PATCH 0385/1232] ci_build.sh: make cleanup less noisy --- ci_build.sh | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index cbd8c0e392..f613b2a05c 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -166,6 +166,7 @@ esac [ -n "$MAKE_FLAGS_QUIET" ] || MAKE_FLAGS_QUIET="VERBOSE=0 V=0 -s" [ -n "$MAKE_FLAGS_VERBOSE" ] || MAKE_FLAGS_VERBOSE="VERBOSE=1 V=1 -s" +[ -n "$MAKE_FLAGS_CLEAN" ] || MAKE_FLAGS_CLEAN="${MAKE_FLAGS_QUIET}" # This is where many symlinks like "gcc -> ../bin/ccache" reside # (note: a "-" value requests to NOT use a CI_CCACHE_SYMLINKDIR; @@ -652,10 +653,11 @@ optional_maintainer_clean_check() { [ -z "$CI_TIME" ] || echo "`date`: Starting maintainer-clean check of currently tested project..." # Note: currently Makefile.am has just a dummy "distcleancheck" rule - $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS maintainer-clean || return + $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN maintainer-clean || return GIT_ARGS="--ignored" check_gitignore "maintainer-clean" || return fi + return 0 } @@ -676,7 +678,7 @@ optional_dist_clean_check() { [ -z "$CI_TIME" ] || echo "`date`: Starting dist-clean check of currently tested project..." # Note: currently Makefile.am has just a dummy "distcleancheck" rule - $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS distclean || return + $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN distclean || return check_gitignore "distclean" || return fi @@ -1260,7 +1262,9 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp if [ -s Makefile ]; then # Let initial clean-up be at default verbosity echo "=== Starting initial clean-up (from old build products)" - ${MAKE} maintainer-clean -k || ${MAKE} distclean -k || true + ${MAKE} maintainer-clean $MAKE_FLAGS_CLEAN -k \ + || ${MAKE} distclean $MAKE_FLAGS_CLEAN -k \ + || true echo "=== Finished initial clean-up" fi @@ -1466,7 +1470,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # would just re-evaluate `configure` to update the # Makefile to remove it and other generated data. #echo "=== Clean the sandbox, $BUILDSTODO build variants remaining..." - #$MAKE distclean -k || true + #$MAKE distclean $MAKE_FLAGS_CLEAN -k || true echo "=== Starting NUT_SSL_VARIANT='$NUT_SSL_VARIANT', $BUILDSTODO build variants remaining..." case "$NUT_SSL_VARIANT" in @@ -1549,7 +1553,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp echo "=== Completed sandbox cleanup-check after NUT_SSL_VARIANT=${NUT_SSL_VARIANT}, $BUILDSTODO build variants remaining" else if [ "$BUILDSTODO" -gt 0 ] && [ "${DO_CLEAN_CHECK-}" != no ]; then - $MAKE distclean -k || echo "WARNING: 'make distclean' FAILED: $? ... proceeding" >&2 + $MAKE distclean $MAKE_FLAGS_CLEAN -k \ + || echo "WARNING: 'make distclean' FAILED: $? ... proceeding" >&2 echo "=== Completed sandbox cleanup after NUT_SSL_VARIANT=${NUT_SSL_VARIANT}, $BUILDSTODO build variants remaining" else echo "=== SKIPPED sandbox cleanup because DO_CLEAN_CHECK=$DO_CLEAN_CHECK and $BUILDSTODO build variants remaining" @@ -1680,7 +1685,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp echo "=== Completed sandbox cleanup-check after NUT_USB_VARIANT=${NUT_USB_VARIANT}, $BUILDSTODO build variants remaining" else if [ "$BUILDSTODO" -gt 0 ] && [ "${DO_CLEAN_CHECK-}" != no ]; then - $MAKE distclean -k || echo "WARNING: 'make distclean' FAILED: $? ... proceeding" >&2 + $MAKE distclean $MAKE_FLAGS_CLEAN -k \ + || echo "WARNING: 'make distclean' FAILED: $? ... proceeding" >&2 echo "=== Completed sandbox cleanup after NUT_USB_VARIANT=${NUT_USB_VARIANT}, $BUILDSTODO build variants remaining" else echo "=== SKIPPED sandbox cleanup because DO_CLEAN_CHECK=$DO_CLEAN_CHECK and $BUILDSTODO build variants remaining" @@ -1791,7 +1797,7 @@ bindings) if [ -s Makefile ]; then # Let initial clean-up be at default verbosity echo "=== Starting initial clean-up (from old build products)" - ${MAKE} realclean -k || true + ${MAKE} realclean $MAKE_FLAGS_CLEAN -k || true echo "=== Finished initial clean-up" fi From a4cc507ed6c0ad45cdf1adde7ff1b5b38d4465ae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 01:52:27 +0100 Subject: [PATCH 0386/1232] ci_build.sh: for developer builds, disable silent rules to see all problems better --- ci_build.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index f613b2a05c..177135c822 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1795,9 +1795,10 @@ bindings) cd "${SCRIPTDIR}" if [ -s Makefile ]; then + # Help developers debug: # Let initial clean-up be at default verbosity echo "=== Starting initial clean-up (from old build products)" - ${MAKE} realclean $MAKE_FLAGS_CLEAN -k || true + ${MAKE} realclean -k || true echo "=== Finished initial clean-up" fi @@ -1820,6 +1821,9 @@ bindings) # from somehow interfering with the running daemons. if [ x"${INPLACE_RUNTIME-}" = xtrue ] || [ x"${BUILD_TYPE-}" = xinplace ] ; then CONFIG_OPTS+=("--enable-inplace-runtime") + else + # Help developers debug: + CONFIG_OPTS+=("--disable-silent-rules") fi ${CONFIGURE_SCRIPT} "${CONFIG_OPTS[@]}" From c9f0d1032fb550cc410f3a3591c6505bd7e9aa82 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 01:57:49 +0100 Subject: [PATCH 0387/1232] */Makefile.am: use AM_V_at for optionally-quieter cleanup --- Makefile.am | 6 +++--- clients/Makefile.am | 2 +- common/Makefile.am | 2 +- docs/Makefile.am | 2 +- docs/man/Makefile.am | 2 +- drivers/Makefile.am | 2 +- include/Makefile.am | 2 +- scripts/python/Makefile.am | 4 ++-- server/Makefile.am | 2 +- tests/Makefile.am | 2 +- tests/NIT/Makefile.am | 2 +- tools/nut-scanner/Makefile.am | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile.am b/Makefile.am index 75caf8a7d2..7b87c013ba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,7 +97,7 @@ MAINTAINERCLEANFILES += Makefile.in .dirstamp include/config.h.in # Executed after default rules maintainer-clean-local: - rm -f missing || true + $(AM_V_at)rm -f missing || true # Do not let $SUBDIRS/Makefile rules delete their local .deps because # this breaks our ability to clean up (e.g. some common/.../*.Plo files @@ -111,8 +111,8 @@ distclean-local: ( cd "$${DIR}" && $(MAKE) -s distclean ) || exit ; \ fi ; \ done - rm -rf .inst tmp autom4te.cache - find "$(builddir)" -type d -name '.deps' | while read DIR ; do rm -rf "$${DIR}" ; done + $(AM_V_at)rm -rf .inst tmp autom4te.cache + $(AM_V_at)find "$(builddir)" -type d -name '.deps' | while read DIR ; do rm -rf "$${DIR}" ; done # Hook the documentation building and validating recipes # Note: these are optionally available (as determined during configure runs) diff --git a/clients/Makefile.am b/clients/Makefile.am index 5117e0dbbf..e9685eeeef 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -133,4 +133,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps diff --git a/common/Makefile.am b/common/Makefile.am index 4fbae5f41c..e30efd6428 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -94,4 +94,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps diff --git a/docs/Makefile.am b/docs/Makefile.am index a3ef137931..327c1bb0fd 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -143,7 +143,7 @@ CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css # Dirs to clean clean-local: - rm -rf *.chunked *.bak tmp + $(AM_V_at)rm -rf *.chunked *.bak tmp ### TODO: automatic dependency generation # Add other directory deps (not for local EXTRA_DIST) and generated contents diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 3dcf7f609b..b11465d1b2 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -1057,4 +1057,4 @@ spellcheck spellcheck-interactive spellcheck-sortdict: MAINTAINERCLEANFILES = Makefile.in .dirstamp clean-local: - rm -rf tmp + $(AM_V_at)rm -rf tmp diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 393845be13..d5ebd10229 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -364,4 +364,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps diff --git a/include/Makefile.am b/include/Makefile.am index f1ac7be3b2..38e1c69c45 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -44,4 +44,4 @@ FORCE: # deps of a local target, we must clean it by ourselves before the # distribution dist-hook: - rm -f $(distdir)/nut_version.h + $(AM_V_at)rm -f $(distdir)/nut_version.h diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 31c3f5cc66..542989d82c 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -165,5 +165,5 @@ endif MAINTAINERCLEANFILES = Makefile.in .dirstamp clean-local: - rm -rf *.pyc __pycache__ */*.pyc */__pycache__ */*/*.pyc */*/__pycache__ - rm -f NUT-Monitor + $(AM_V_at)rm -rf *.pyc __pycache__ */*.pyc */__pycache__ */*/*.pyc */*/__pycache__ + $(AM_V_at)rm -f NUT-Monitor diff --git a/server/Makefile.am b/server/Makefile.am index 1198ec61eb..7e0b5d1074 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -45,4 +45,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps diff --git a/tests/Makefile.am b/tests/Makefile.am index 5b58de509d..7cd1d984fb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -133,4 +133,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps diff --git a/tests/NIT/Makefile.am b/tests/NIT/Makefile.am index 63762314f4..cf69699664 100644 --- a/tests/NIT/Makefile.am +++ b/tests/NIT/Makefile.am @@ -23,4 +23,4 @@ check-NIT-devel: $(abs_srcdir)/nit.sh MAINTAINERCLEANFILES = Makefile.in .dirstamp clean-local: - rm -rf tmp + $(AM_V_at)rm -rf tmp diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 354b3f6f41..9707a29063 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -149,4 +149,4 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! #clean-local: -# rm -rf $(builddir)/.deps +# $(AM_V_at)rm -rf $(builddir)/.deps From 0176b6fb51c91dd8db625d9d99c000ba3fcce7dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 02:12:22 +0100 Subject: [PATCH 0388/1232] ci_build.sh: make maintainer-clean less noisy in CI if V=0 (automake clean.m4 echoes unconditionally) --- ci_build.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 177135c822..156294c919 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -653,7 +653,13 @@ optional_maintainer_clean_check() { [ -z "$CI_TIME" ] || echo "`date`: Starting maintainer-clean check of currently tested project..." # Note: currently Makefile.am has just a dummy "distcleancheck" rule - $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN maintainer-clean || return + case "$MAKE_FLAGS $DISTCHECK_FLAGS $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN" in + *V=0*) + $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN maintainer-clean > /dev/null || return + ;; + *) + $CI_TIME $MAKE DISTCHECK_FLAGS="$DISTCHECK_FLAGS" $PARMAKE_FLAGS $MAKE_FLAGS_CLEAN maintainer-clean || return + esac GIT_ARGS="--ignored" check_gitignore "maintainer-clean" || return fi @@ -1262,7 +1268,14 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp if [ -s Makefile ]; then # Let initial clean-up be at default verbosity echo "=== Starting initial clean-up (from old build products)" - ${MAKE} maintainer-clean $MAKE_FLAGS_CLEAN -k \ + case "$MAKE_FLAGS $MAKE_FLAGS_CLEAN" in + *V=0*) + ${MAKE} maintainer-clean $MAKE_FLAGS_CLEAN -k > /dev/null \ + || ${MAKE} maintainer-clean $MAKE_FLAGS_CLEAN -k + ;; + *) + ${MAKE} maintainer-clean $MAKE_FLAGS_CLEAN -k + esac \ || ${MAKE} distclean $MAKE_FLAGS_CLEAN -k \ || true echo "=== Finished initial clean-up" From 6c130d9e83744d02b1dc61b120f6e512d815c05d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 02:27:51 +0100 Subject: [PATCH 0389/1232] ci_build.sh: shuffle quotes in NUT_*_VARIANT=... reports for easier search in logs --- ci_build.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 156294c919..bbf4207e1f 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1485,7 +1485,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp #echo "=== Clean the sandbox, $BUILDSTODO build variants remaining..." #$MAKE distclean $MAKE_FLAGS_CLEAN -k || true - echo "=== Starting NUT_SSL_VARIANT='$NUT_SSL_VARIANT', $BUILDSTODO build variants remaining..." + echo "=== Starting 'NUT_SSL_VARIANT=$NUT_SSL_VARIANT', $BUILDSTODO build variants remaining..." case "$NUT_SSL_VARIANT" in ""|auto|default) # Quietly build one scenario, whatever we can (or not) @@ -1500,7 +1500,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp ) ;; *) - echo "=== Building with NUT_SSL_VARIANT='${NUT_SSL_VARIANT}' ..." + echo "=== Building with 'NUT_SSL_VARIANT=${NUT_SSL_VARIANT}' ..." ( CONFIG_OPTS+=("--with-${NUT_SSL_VARIANT}") configure_nut ) @@ -1517,7 +1517,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp continue } - echo "=== Configured NUT_SSL_VARIANT='$NUT_SSL_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." + echo "=== Configured 'NUT_SSL_VARIANT=$NUT_SSL_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." cd "${CI_BUILDDIR}" build_to_only_catch_errors && { SUCCEEDED="${SUCCEEDED} NUT_SSL_VARIANT=${NUT_SSL_VARIANT}[build]" @@ -1591,7 +1591,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp || [ "$CI_FAILFAST" = "true" -a "$RES_ALLERRORS" = 0 ] \ ) && \ for NUT_USB_VARIANT in $NUT_USB_VARIANTS ; do - echo "=== Starting NUT_USB_VARIANT='$NUT_USB_VARIANT', $BUILDSTODO build variants remaining..." + echo "=== Starting 'NUT_USB_VARIANT=$NUT_USB_VARIANT', $BUILDSTODO build variants remaining..." case "$NUT_USB_VARIANT" in ""|auto|default) # Quietly build one scenario, whatever we can (or not) @@ -1618,7 +1618,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp ) ;; libusb-*) - echo "=== Building with NUT_USB_VARIANT='${NUT_USB_VARIANT}' ..." + echo "=== Building with 'NUT_USB_VARIANT=${NUT_USB_VARIANT}' ..." ( if [ "$NUT_SSL_VARIANTS" != "auto" ] ; then CONFIG_OPTS+=("--without-all") CONFIG_OPTS+=("--without-ssl") @@ -1629,7 +1629,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp ) ;; *) - echo "=== Building with NUT_USB_VARIANT='${NUT_USB_VARIANT}' ..." + echo "=== Building with 'NUT_USB_VARIANT=${NUT_USB_VARIANT}' ..." ( if [ "$NUT_SSL_VARIANTS" != "auto" ] ; then CONFIG_OPTS+=("--without-all") CONFIG_OPTS+=("--without-ssl") @@ -1651,7 +1651,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp continue } - echo "=== Configured NUT_USB_VARIANT='$NUT_USB_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." + echo "=== Configured 'NUT_USB_VARIANT=$NUT_USB_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." cd "${CI_BUILDDIR}" build_to_only_catch_errors && { SUCCEEDED="${SUCCEEDED} NUT_USB_VARIANT=${NUT_USB_VARIANT}[build]" From 09cb72335d7fe5fa3457cc988a39fb0eb6aedb3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 11:27:48 +0100 Subject: [PATCH 0390/1232] scripts/systemd/*.service.in: ExecStartPre systemd-tmpfiles to facilitate install/upgrade with less fuss Inspired by Fedora Rawhide patches at https://src.fedoraproject.org/rpms/nut/blob/0a29e563e374f274f801270bce8eaab9159c7d16/f/nut-2.6.3-tmpfiles.patch --- scripts/systemd/nut-driver-enumerator.service.in | 1 + scripts/systemd/nut-driver@.service.in | 1 + scripts/systemd/nut-monitor.service.in | 1 + scripts/systemd/nut-server.service.in | 1 + 4 files changed, 4 insertions(+) diff --git a/scripts/systemd/nut-driver-enumerator.service.in b/scripts/systemd/nut-driver-enumerator.service.in index 51e6d152da..ef46a4ad8f 100644 --- a/scripts/systemd/nut-driver-enumerator.service.in +++ b/scripts/systemd/nut-driver-enumerator.service.in @@ -23,6 +23,7 @@ Type=oneshot # don't want it to fail the unit (when it can't restart). Environment=REPORT_RESTART_42=no EnvironmentFile=-@CONFPATH@/nut.conf +ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh ExecReload=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 2b903ca49a..96a9c97494 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -43,6 +43,7 @@ PartOf=nut-driver.target Environment=NUT_IGNORE_NOWAIT=true EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N +ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl stop "$NUTDEV"' # Restart really always, do not stop trying: diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index b8a86bdb1a..ef6891f9f1 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -21,6 +21,7 @@ PartOf=nut.target [Service] EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N +ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@SBINDIR@/upsmon @SYSTEMD_DAEMON_ARGS_UPSMON@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 7a3f1096db..49fb0a9bae 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -25,6 +25,7 @@ SyslogIdentifier=%N # Note: foreground mode "-F" by default skips writing a PID file (and # needs default Type=simple); we can use "-FF" here to create the file # anyway, so that old "upsd -c reload" works rather than systemd action: +ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID # No tracking for PIDFile path and service attribute here (it might not From 6dab6d64b2a8e7efca76d4bca194afdc414fa301 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 11:37:46 +0100 Subject: [PATCH 0391/1232] scripts/systemd/*.service.in: parameterize systemd-tmpfiles program location --- configure.ac | 5 +++++ scripts/systemd/nut-driver-enumerator.service.in | 2 +- scripts/systemd/nut-driver@.service.in | 2 +- scripts/systemd/nut-monitor.service.in | 2 +- scripts/systemd/nut-server.service.in | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 4615a96e2c..3d8c5d1054 100644 --- a/configure.ac +++ b/configure.ac @@ -2728,6 +2728,10 @@ else AC_MSG_RESULT(no) fi +dnl What pathname would we embed into unit files ExecStartPre? +dnl TODO? Any need to make it a --with-... argument? +AC_CHECK_PROGS([SYSTEMD_TMPFILES_PROGRAM], [systemd-tmpfiles], [/usr/bin/systemd-tmpfiles]) + dnl Note: we may want binaries with sd_notify and similar features regardless dnl of building and delivering unit files (which may be crafted separately). @@ -3439,6 +3443,7 @@ AC_SUBST(SYSTEMD_DAEMON_NOTIFYACCESS_UPSMON) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSD) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_UPSMON) AC_SUBST(SYSTEMD_DAEMON_WATCHDOG_DRIVER) +AC_SUBST(SYSTEMD_TMPFILES_PROGRAM) AC_SUBST(DRIVER_BUILD_LIST) AC_SUBST(DRIVER_MAN_LIST) AC_SUBST(DRIVER_MAN_LIST_PAGES) diff --git a/scripts/systemd/nut-driver-enumerator.service.in b/scripts/systemd/nut-driver-enumerator.service.in index ef46a4ad8f..7ede5a31d1 100644 --- a/scripts/systemd/nut-driver-enumerator.service.in +++ b/scripts/systemd/nut-driver-enumerator.service.in @@ -23,7 +23,7 @@ Type=oneshot # don't want it to fail the unit (when it can't restart). Environment=REPORT_RESTART_42=no EnvironmentFile=-@CONFPATH@/nut.conf -ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf +ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh ExecReload=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 96a9c97494..5139a28d47 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -43,7 +43,7 @@ PartOf=nut-driver.target Environment=NUT_IGNORE_NOWAIT=true EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N -ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf +ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl stop "$NUTDEV"' # Restart really always, do not stop trying: diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index ef6891f9f1..e39064f690 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -21,7 +21,7 @@ PartOf=nut.target [Service] EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N -ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf +ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@SBINDIR@/upsmon @SYSTEMD_DAEMON_ARGS_UPSMON@ ExecReload=@SBINDIR@/upsmon -c reload PIDFile=@PIDPATH@/upsmon.pid diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 49fb0a9bae..4c29561012 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -25,7 +25,7 @@ SyslogIdentifier=%N # Note: foreground mode "-F" by default skips writing a PID file (and # needs default Type=simple); we can use "-FF" here to create the file # anyway, so that old "upsd -c reload" works rather than systemd action: -ExecStartPre=-/usr/bin/systemd-tmpfiles --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf +ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=@SBINDIR@/upsd @SYSTEMD_DAEMON_ARGS_UPSD@ ExecReload=@SBINDIR@/upsd -c reload -P $MAINPID # No tracking for PIDFile path and service attribute here (it might not From d39340a90fdfe7f5552475a2cb0701c0909e47f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 12:12:36 +0100 Subject: [PATCH 0392/1232] scripts/python/*: import definition and use-case of CheckUPSAvailable() from Fedora packaging patches Py2: https://src.fedoraproject.org/rpms/nut/blob/3c9fea3a359db592e3c7d25ff5c8050325b21dfe/f/nut-2.6.5-unreachable.patch Py3: https://src.fedoraproject.org/rpms/nut/blob/48685366900985696be8371d8deea6494ae36c43/f/nut-2.6.5-unreachable.patch by Michal Hlavinka --- scripts/python/app/NUT-Monitor-py2gtk2.in | 5 +++++ scripts/python/app/NUT-Monitor-py3qt5.in | 5 +++++ scripts/python/module/PyNUT.py.in | 25 ++++++++++++++++++++-- scripts/python/module/README | 25 ++++++++++++++++++++++ scripts/python/module/test_nutclient.py.in | 4 ++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/scripts/python/app/NUT-Monitor-py2gtk2.in b/scripts/python/app/NUT-Monitor-py2gtk2.in index d845e87058..5c16aa3a77 100755 --- a/scripts/python/app/NUT-Monitor-py2gtk2.in +++ b/scripts/python/app/NUT-Monitor-py2gtk2.in @@ -683,6 +683,11 @@ class interface : self.gui_status_notification( _("Device '%s' not found on server") % self.__current_ups, "warning.png" ) return + if not self.__ups_handler.CheckUPSAvailable( self.__current_ups ): + self.gui_status_message( _("UPS '{0}' is not reachable").format( self.__current_ups ) ) + self.gui_status_notification( _("UPS '{0}' is not reachable").format( self.__current_ups ), "warning.png" ) + return + self.__connected = True self.__widgets["ups_connect"].hide() self.__widgets["ups_disconnect"].show() diff --git a/scripts/python/app/NUT-Monitor-py3qt5.in b/scripts/python/app/NUT-Monitor-py3qt5.in index 8092c39e15..d78f4160a4 100755 --- a/scripts/python/app/NUT-Monitor-py3qt5.in +++ b/scripts/python/app/NUT-Monitor-py3qt5.in @@ -705,6 +705,11 @@ along with this program. If not, see . self.gui_status_notification( _("Device '%s' not found on server") % self.__current_ups, "warning.png" ) return + if not self.__ups_handler.CheckUPSAvailable( self.__current_ups ): + self.gui_status_message( _("UPS '{0}' is not reachable").format( self.__current_ups ) ) + self.gui_status_notification( _("UPS '{0}' is not reachable").format( self.__current_ups ), "warning.png" ) + return + self.__connected = True self.__widgets["ups_connect"].hide() self.__widgets["ups_disconnect"].show() diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in index 0be62ae822..451f80de04 100644 --- a/scripts/python/module/PyNUT.py.in +++ b/scripts/python/module/PyNUT.py.in @@ -51,6 +51,10 @@ # Fixed raised PyNUTError() exceptions to carry a Python string # (suitable for Python2 and Python3), not byte array from protocol, # so exception catchers can process them naturally (see test script). +# +# 2023-01-18 Jim Klimov - Version 1.6.0 +# Added CheckUPSAvailable() method originally by Michal Hlavinka +# from 2013-01-07 RedHat/Fedora packaging import telnetlib @@ -69,8 +73,8 @@ class PyNUTClient : __timeout = None __srv_handler = None - __version = "1.5.0" - __release = "2022-08-12" + __version = "1.6.0" + __release = "2023-01-18" def __init__( self, host="127.0.0.1", port=3493, login=None, password=None, debug=False, timeout=5 ) : @@ -206,6 +210,23 @@ available vars. return( ups_vars ) + def CheckUPSAvailable( self, ups="" ) : + """ Check whether UPS is reachable + +Just tries to contact UPS with a safe command. +The result is True (reachable) or False (unreachable) + """ + if self.__debug : + print( "[DEBUG] CheckUPSAvailable called..." ) + + self.__srv_handler.write( "LIST CMD %s\n" % ups ) + result = self.__srv_handler.read_until( "\n" ) + if result != "BEGIN LIST CMD %s\n" % ups : + return False + + self.__srv_handler.read_until( "END LIST CMD %s\n" % ups ) + return True + def GetUPSCommands( self, ups="" ) : """ Get all available commands for the specified UPS diff --git a/scripts/python/module/README b/scripts/python/module/README index 70bad4b4cf..b9ae10a0ee 100644 --- a/scripts/python/module/README +++ b/scripts/python/module/README @@ -65,6 +65,8 @@ class PyNUTClient : def FSD( self, ups="" ) : + def CheckUPSAvailable( self, ups="" ) : + def GetRWVars( self, ups='' ) : def GetUPSCommands( self, ups='' ) : @@ -148,6 +150,29 @@ in case of failure, such as that this server does not allow to manage that UPS as a "primary" (or "master" before NUT 2.8.0). +CheckUPSAvailable +~~~~~~~~~~~~~~~~~ + +Returns a boolean state whether the specified UPS is recognized and available +(`True`), or is not (`False`). + +Internally, requests a listing of commands supported by the device name, and +evaluates the server response. + +.Example +----- + import PyNUT + + ups = PyNUT.PyNUTClient( host='serveur', login='upsadmin', password='upspass' ) + result = ups.CheckUPSAvailable( ups='ups1' ) + print( result ) + + >> True +----- + +See also: `GetUPSCommands()` + + GetRWVars ~~~~~~~~~ diff --git a/scripts/python/module/test_nutclient.py.in b/scripts/python/module/test_nutclient.py.in index 792688c866..c9b1431447 100755 --- a/scripts/python/module/test_nutclient.py.in +++ b/scripts/python/module/test_nutclient.py.in @@ -34,6 +34,10 @@ if __name__ == "__main__" : result = nut.GetUPSVars( "dummy" ) print( "\033[01;33m%s\033[0m\n" % result ) + print( 80*"-" + "\nTesting 'CheckUPSAvailable' :") + result = nut.CheckUPSAvailable( "dummy" ) + print( "\033[01;33m%s\033[0m\n" % result ) + print( 80*"-" + "\nTesting 'GetUPSCommands' :") result = nut.GetUPSCommands( "dummy" ) print( "\033[01;33m%s\033[0m\n" % result ) From 8712ce824adc6ce118731c3a277e6efe9d564c9a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 12:24:34 +0100 Subject: [PATCH 0393/1232] scripts/python/module/PyNUT.py.in: update for dual Py2/Py3 citizenship --- scripts/python/module/PyNUT.py.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in index 451f80de04..6f3c4ff510 100644 --- a/scripts/python/module/PyNUT.py.in +++ b/scripts/python/module/PyNUT.py.in @@ -219,12 +219,12 @@ The result is True (reachable) or False (unreachable) if self.__debug : print( "[DEBUG] CheckUPSAvailable called..." ) - self.__srv_handler.write( "LIST CMD %s\n" % ups ) - result = self.__srv_handler.read_until( "\n" ) - if result != "BEGIN LIST CMD %s\n" % ups : + self.__srv_handler.write( ("LIST CMD %s\n" % ups).encode('ascii') ) + result = self.__srv_handler.read_until( b"\n" ) + if result != ("BEGIN LIST CMD %s\n" % ups).encode('ascii') : return False - self.__srv_handler.read_until( "END LIST CMD %s\n" % ups ) + self.__srv_handler.read_until( ("END LIST CMD %s\n" % ups).encode('ascii') ) return True def GetUPSCommands( self, ups="" ) : From 08990ed41f9dc3e94f4585815b35f7d89998298a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Jan 2023 21:01:11 +0100 Subject: [PATCH 0394/1232] Bump commented suggestions to automake-1.13 or newer Follow-up to #1821 --- autogen.sh | 2 +- configure.ac | 9 +++++++-- docs/config-prereqs.txt | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/autogen.sh b/autogen.sh index 0f330ad4f7..c591f9dbed 100755 --- a/autogen.sh +++ b/autogen.sh @@ -122,7 +122,7 @@ FAILED: did not generate an executable configure script! # Note: on some systems "autoreconf", "automake" et al are dispatcher # scripts, and need you to explicitly say which version you want, e.g. -# export AUTOCONF_VERSION=2.65 AUTOMAKE_VERSION=1.10 +# export AUTOCONF_VERSION=2.65 AUTOMAKE_VERSION=1.13 # If you get issues with AC_DISABLE_STATIC make sure you have libtool. EOF exit 1 diff --git a/configure.ac b/configure.ac index 3c452d1880..cb6ff28312 100644 --- a/configure.ac +++ b/configure.ac @@ -35,12 +35,17 @@ AC_CONFIG_HEADERS([include/config.h]) AC_PREFIX_DEFAULT(/usr/local/ups) AM_INIT_AUTOMAKE([subdir-objects]) -dnl `configure --enable-silent-rules` or `make V=1` for details: -AM_SILENT_RULES([yes]) +dnl Default to `configure --enable-silent-rules` or `make V=1` for details? +dnl This feature seems to require automake-1.13 or newer (1.11+ by other info) +dnl On very old systems can comment it away with little loss (then automake-1.10 +dnl is known to suffice): +ifdef(`AM_SILENT_RULES', `AM_SILENT_RULES([yes])') +dnl, `AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])' ) dnl we need Autoconf 2.61 or better to enable features of Posix that are extensions to C dnl (and actually 2.64 or better for m4/ax_check_compile_flag.m4 when it is sourced) dnl UPDATE: As tested on CentOS 6, its "autoconf-2.63-5.1.el6.noarch" also suffices. +dnl But OpenBSD 6.5 requires autoconf-2.65 and automake-1.13 or newer... AC_MSG_CHECKING(for autoconf macro to enable system extensions) m4_version_prereq(2.61, [ AC_MSG_RESULT(yes) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 1156fde5d3..1dd555216e 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -586,7 +586,7 @@ During builds, you may have to tell system dispatcher scripts which version to use (which feels inconvenient, but on the up-side for CI -- this system allows to test many versions of auto-tools in the same agent), e.g.: ------ -:; export AUTOCONF_VERSION=2.69 AUTOMAKE_VERSION=1.10 +:; export AUTOCONF_VERSION=2.69 AUTOMAKE_VERSION=1.13 ------ To use the `ci_build.sh` don't forget `bash` which is not part of OpenBSD From ce52ed297818f426a9db37eff36a8364a9462211 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 19 Jan 2023 18:54:43 +0100 Subject: [PATCH 0395/1232] configure.ac: prepare nut-common-tmpfiles.conf.in subdir for @STATEPATH@/upssched, and update comments --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cb6ff28312..08ac1f305a 100644 --- a/configure.ac +++ b/configure.ac @@ -3862,20 +3862,25 @@ AC_MSG_CHECKING([whether to customize ${TOP_BUILDDIR}/scripts/systemd/nut-common AS_IF([test -n "$systemdtmpfilesdir"], [mkdir -p "${TOP_BUILDDIR}"/scripts/systemd cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF -# State file (e.g. upsd to driver) and pidfile location for NUT: +# See also: https://github.com/networkupstools/nut/wiki/Technicalities:-Work-with-PID-and-state-file-paths#pidpath-altpidpath-statepath +# State file (e.g. upsd to driver pipes) and PID file location for NUT: d @STATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - +# Default PIPEFN and LOCKFN locations per upssched.conf: +d @STATEPATH@/upssched 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @STATEPATH@ EOF AS_IF([test "$STATEPATH" != "$PIDPATH"], [AS_CASE(["${PIDPATH}"], [*/run|*/tmp|*/shm], [], dnl Do not intrude into system paths; TODO: add more if appropriate for some Linux distro [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF +# Primarily used by upsmon and upslog, possibly running as root: d @PIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @PIDPATH@ EOF ])]) AS_IF([test -n "$ALTPIDPATH" && test "$STATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTPIDPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF +# Can be used as upsd and driver PID file location for NUT: d @ALTPIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @ALTPIDPATH@ EOF]) From 87807397822d97725a5e10c43637b5e9aa91b6f4 Mon Sep 17 00:00:00 2001 From: Neil Romig Date: Fri, 20 Jan 2023 14:39:55 +0000 Subject: [PATCH 0396/1232] Update nut-driver-enumerator.sh.in Remove backslash from grep expression at line 836 to avoid grep warning of stray backslash. --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index 02f4f88c9b..ac0a422ee7 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -833,7 +833,7 @@ upslist_normalizeFile_filter() { -e 's,=\"\([^\ '"$TABCHAR"']*\)\"$,=\1,' \ -e 's,^\(\[[^]'"$TABCHAR"'\ ]*\]\)['"$TABCHAR"'\ ]*\(#.*\)*$,\1,' \ | grep -E -v '^$' \ - | grep -E '([\[\=]|^[^ '"$TABCHAR"']*$|^[^ '"$TABCHAR"']*[ '"$TABCHAR"']*\#.*$)' + | grep -E '([\[\=]|^[^ '"$TABCHAR"']*$|^[^ '"$TABCHAR"']*[ '"$TABCHAR"']*#.*$)' } upslist_normalizeFile() { From 719350a376b2bf065001e0629b8fea46050028e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 13:37:40 +0100 Subject: [PATCH 0397/1232] lib/libupsclient-config.in: comment that NUT_VERSION_MACRO in binaries may differ from PACKAGE_VERSION in the script [#1826] --- lib/libupsclient-config.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/libupsclient-config.in b/lib/libupsclient-config.in index 97cd6d0749..f24b6685c3 100644 --- a/lib/libupsclient-config.in +++ b/lib/libupsclient-config.in @@ -7,6 +7,11 @@ # See the distribution lib/README for usage information # # **********************************************************# +# Note: PACKAGE_VERSION is baked into configure script used +# to prepare the build of NUT deployed here. Actual programs +# report a NUT_VERSION_MACRO which may differ if NUT was built +# from Git and not a release or snapshot "dist" tarball (value +# is determined during build then). Version="@PACKAGE_VERSION@" prefix="@prefix@" exec_prefix="@exec_prefix@" From 630f0d1d33439d47302ec02f934b2899749ac5b7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 13:44:09 +0100 Subject: [PATCH 0398/1232] configure.ac: do not track in CONFIG_FLAGS that we --disable-runtime-support, and only track once that we --enable-runtime-support [#1826] --- configure.ac | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index cb6ff28312..6d98a05f44 100644 --- a/configure.ac +++ b/configure.ac @@ -10,15 +10,31 @@ AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) dnl Keep track of command-line options passed to this script: CONFIG_FLAGS="" dnl Keep each token quoted, in case spaces or other special chars crawl in: +_flag_enable_inplace_runtime=no for F in "$@" ; do case "$F" in *=*" "*) NF="$(echo "$F" | sed "s,=,=',")""'" && F="$NF" ;; esac - test -z "${CONFIG_FLAGS}" \ - && CONFIG_FLAGS="$F" \ - || CONFIG_FLAGS="${CONFIG_FLAGS} $F" + case "$F" in + --disable-runtime-support|--enable-runtime-support=no) ;; + --enable-runtime-support*) _flag_enable_inplace_runtime=yes ;; + *) + test -z "${CONFIG_FLAGS}" \ + && CONFIG_FLAGS="$F" \ + || CONFIG_FLAGS="${CONFIG_FLAGS} $F" + ;; + esac done +dnl Keep it "known" that we tried to re-use at least some local configuration +dnl so unspecified options are not necessarily at default values for this script +AS_IF([test x"${_flag_enable_inplace_runtime}" = xyes], [ + F="--enable-runtime-support" + test -z "${CONFIG_FLAGS}" \ + && CONFIG_FLAGS="$F" \ + || CONFIG_FLAGS="${CONFIG_FLAGS} $F" + ]) +unset _flag_enable_inplace_runtime unset F unset NF AC_DEFINE_UNQUOTED([CONFIG_FLAGS],["${CONFIG_FLAGS}"],[Flags passed to configure script]) From 4d64fa0c991e33f310bf35dcfff973e7df8618df Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 14:02:36 +0100 Subject: [PATCH 0399/1232] Refactor nut_report_config_flags() from many programs into common.c [#1826, #1709] --- clients/upsc.c | 6 ++---- clients/upscmd.c | 6 ++---- clients/upslog.c | 6 ++---- clients/upsmon.c | 8 +++----- clients/upsrw.c | 6 ++---- common/common.c | 6 ++++++ drivers/main.c | 6 ++---- include/common.h | 5 +++++ server/upsd.c | 6 ++---- tools/nut-scanner/nut-scanner.c | 8 ++------ 10 files changed, 28 insertions(+), 35 deletions(-) diff --git a/clients/upsc.c b/clients/upsc.c index 6181e6bfed..5cc2a4d8cc 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -57,8 +57,7 @@ static void usage(const char *prog) printf(" -c - lists each client connected on , one per line.\n"); printf(" - upsd server, [@[:]] form\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); } static void printvar(const char *var) @@ -235,8 +234,7 @@ int main(int argc, char **argv) break; case 'V': - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); #ifndef HAVE___ATTRIBUTE__NORETURN diff --git a/clients/upscmd.c b/clients/upscmd.c index be24a6e2c2..a5223baa57 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -65,8 +65,7 @@ static void usage(const char *prog) printf(" Valid instant command - test.panel.start, etc.\n"); printf(" [] Additional data for command - number of seconds, etc.\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); } static void print_cmd(char *cmdname) @@ -312,8 +311,7 @@ int main(int argc, char **argv) break; case 'V': - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); #ifndef HAVE___ATTRIBUTE__NORETURN diff --git a/clients/upslog.c b/clients/upslog.c index ae151c83c0..b18be40714 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -176,8 +176,7 @@ static void help(const char *prog) printf("\n"); printf("See the upslog(8) man page for more information.\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); } @@ -504,8 +503,7 @@ int main(int argc, char **argv) break; case 'V': - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); case 'p': diff --git a/clients/upsmon.c b/clients/upsmon.c index b7c07f6e00..b959c42ebf 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2182,8 +2182,7 @@ static void help(const char *arg_progname) printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); } @@ -2500,9 +2499,8 @@ int main(int argc, char *argv[]) run_as_user = xstrdup(optarg); break; case 'V': - /* just show the banner */ - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + /* just show the optional CONFIG_FLAGS banner */ + nut_report_config_flags(); exit(EXIT_SUCCESS); case '4': opt_af = AF_INET; diff --git a/clients/upsrw.c b/clients/upsrw.c index 0148baed20..229237225e 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -66,8 +66,7 @@ static void usage(const char *prog) printf("\n"); printf("Call without -s to show all possible read/write variables (same as -l).\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); } static void clean_exit(void) @@ -669,8 +668,7 @@ int main(int argc, char **argv) break; case 'V': printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); case 'h': default: diff --git a/common/common.c b/common/common.c index 88469790b3..7a7a7511ec 100644 --- a/common/common.c +++ b/common/common.c @@ -937,6 +937,12 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) return ret; } +void nut_report_config_flags(void) +{ + upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); +} + static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret; diff --git a/drivers/main.c b/drivers/main.c index 362bac6103..eb254a9840 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -134,8 +134,7 @@ static void help_msg(void) { vartab_t *tmp; - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); printf("\nusage: %s (-a |-s ) [OPTIONS]\n", progname); @@ -831,8 +830,7 @@ int main(int argc, char **argv) break; case 'V': /* already printed the banner for program name */ - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); case 'x': splitxarg(optarg); diff --git a/include/common.h b/include/common.h index b2e61abc2d..7119ace6b6 100644 --- a/include/common.h +++ b/include/common.h @@ -312,6 +312,11 @@ void fatal_with_errno(int status, const char *fmt, ...) void fatalx(int status, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))) __attribute__((noreturn)); +/* Report CONFIG_FLAGS used for this build of NUT similarly to how + * upsdebugx(1, ...) would do it, but not limiting the string length + */ +void nut_report_config_flags(void); + extern int nut_debug_level; extern int nut_log_level; diff --git a/server/upsd.c b/server/upsd.c index 135febcc0e..847d8ff398 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1507,8 +1507,7 @@ static void help(const char *arg_progname) printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); } @@ -1636,8 +1635,7 @@ int main(int argc, char **argv) case 'V': /* Note - we already printed the banner for program name */ - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); exit(EXIT_SUCCESS); diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 43b2477c89..345fe4bd99 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -178,8 +178,7 @@ static void show_usage() /* NOTE: This code uses `nutscan_avail_*` global vars from nutscan-init.c */ puts("nut-scanner : utility for detection of available power devices.\n"); - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - NUT_VERSION_MACRO, CONFIG_FLAGS); + nut_report_config_flags(); puts("OPTIONS:"); printf(" -C, --complete_scan: Scan all available devices except serial ports (default).\n"); @@ -652,10 +651,7 @@ int main(int argc, char *argv[]) break; case 'V': printf("Network UPS Tools - %s\n", NUT_VERSION_MACRO); - - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - NUT_VERSION_MACRO, CONFIG_FLAGS); - + nut_report_config_flags(); exit(EXIT_SUCCESS); case 'a': printf("OLDNUT\n"); From 79628b7ec60d9785677b3ef06aa9269d2349a19b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 14:12:21 +0100 Subject: [PATCH 0400/1232] Refactor nut_report_config_flags() from many programs into common.c [#1826, #1709] - bump libs version-info --- clients/Makefile.am | 6 +++--- tools/nut-scanner/Makefile.am | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clients/Makefile.am b/clients/Makefile.am index e9685eeeef..8a2dd61991 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -91,7 +91,7 @@ endif # object .so names would differ) # libupsclient version information -libupsclient_la_LDFLAGS = -version-info 6:0:0 +libupsclient_la_LDFLAGS = -version-info 6:1:0 libupsclient_la_LDFLAGS += -export-symbols-regex ^upscli_ if HAVE_WINDOWS # Many versions of MingW seem to fail to build non-static DLL without this @@ -101,7 +101,7 @@ endif if HAVE_CXX11 # libnutclient version information and build libnutclient_la_SOURCES = nutclient.h nutclient.cpp -libnutclient_la_LDFLAGS = -version-info 2:1:0 +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: libnutclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la @@ -116,7 +116,7 @@ endif if HAVE_CXX11 # libnutclientstub version information and build libnutclientstub_la_SOURCES = nutclientmem.h nutclientmem.cpp -libnutclientstub_la_LDFLAGS = -version-info 1:0:0 +libnutclientstub_la_LDFLAGS = -version-info 1:1:0 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/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 9707a29063..9a1ad343a7 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -78,7 +78,7 @@ endif # object .so names would differ) # # libnutscan version information -libnutscan_la_LDFLAGS += -version-info 2:0:0 +libnutscan_la_LDFLAGS += -version-info 2:1:0 # libnutscan exported symbols regex # WARNING: Since the library includes parts of libcommon (as much as needed @@ -89,7 +89,7 @@ libnutscan_la_LDFLAGS += -version-info 2:0:0 # copies of "nut_debug_level" making fun of our debug-logging attempts. # One solution to tackle if needed for those cases would be to make some # dynamic/shared libnutcommon (etc.) -libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads)' +libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads|nut_report_config_flags)' libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include \ $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers From cd085c1bec1c9bad3879675a56e62f3546d97c2f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 14:37:03 +0100 Subject: [PATCH 0401/1232] common/common.c: refactor nut_report_config_flags() to allow for longer option lists for purposes of "configure --enable-inplace-runtime" [#1826] --- common/common.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index 7a7a7511ec..fff7532a00 100644 --- a/common/common.c +++ b/common/common.c @@ -939,8 +939,23 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) void nut_report_config_flags(void) { - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + /* Roughly similar to upslogx() but without the buffer-size limits and + * timestamp/debug-level prefixes. Only printed if debug (any) is on. + * Depending on amount of configuration tunables involved by a particular + * build of NUT, the string can be quite long (over 1KB). + */ + if (nut_debug_level < 1) + return; + + if (xbit_test(upslog_flags, UPSLOG_STDERR)) + fprintf(stderr, "Network UPS Tools version %s configured with flags: %s\n", + UPS_VERSION, CONFIG_FLAGS); + + /* NOTE: May be ignored or truncated by receiver if that syslog server + * (and/or OS sender) does not accept messages of such length */ + if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) + syslog(LOG_DEBUG, "Network UPS Tools version %s configured with flags: %s", + UPS_VERSION, CONFIG_FLAGS); } static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) From 77bae3482a9a3d7181b67b67d636231f9c2308f9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 16:27:13 +0100 Subject: [PATCH 0402/1232] configure.ac: update comments for systemd/nut-common-tmpfiles.conf.in --- configure.ac | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 08ac1f305a..5be19374e5 100644 --- a/configure.ac +++ b/configure.ac @@ -3859,6 +3859,8 @@ ABS_TOP_SRCDIR="`cd "${abs_srcdir}" && pwd`" || AC_MSG_ERROR([Can not detect ABS AM_CONDITIONAL([BUILDING_IN_TREE], [test "${ABS_TOP_BUILDDIR}" = "${ABS_TOP_SRCDIR}"]) AC_MSG_CHECKING([whether to customize ${TOP_BUILDDIR}/scripts/systemd/nut-common-tmpfiles.conf.in for this system]) +dnl TOTHINK: Some distributions make the directories below owned +dnl by "root:${RUN_AS_GROUP}" with 77x permissions. Is it safer?.. AS_IF([test -n "$systemdtmpfilesdir"], [mkdir -p "${TOP_BUILDDIR}"/scripts/systemd cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF @@ -3880,13 +3882,15 @@ EOF ])]) AS_IF([test -n "$ALTPIDPATH" && test "$STATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTPIDPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF -# Can be used as upsd and driver PID file location for NUT: +# Should be used as upsd and driver PID file location for NUT +# (if ALTPIDPATH differs from STATEPATH): d @ALTPIDPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @ALTPIDPATH@ EOF]) dnl Generally added to support some forks AS_IF([test -n "$ALTSTATEPATH" && test "$STATEPATH" != "$ALTSTATEPATH" && test "$ALTSTATEPATH" != "$ALTPIDPATH" && test "$PIDPATH" != "$ALTSTATEPATH"], [cat >> "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF +# Some NUT variants also maintain an ALTSTATEPATH: d @ALTSTATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - X @ALTSTATEPATH@ EOF]) From 0b8030e24da4c23e4d13524c5b72101c53603744 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 14:59:34 +0100 Subject: [PATCH 0403/1232] configure.ac: track NUT_VERSION_DEPLOYED which we inherit from with --enable-inplace-runtime [#1826] --- configure.ac | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 6d98a05f44..1336f62409 100644 --- a/configure.ac +++ b/configure.ac @@ -10,15 +10,15 @@ AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) dnl Keep track of command-line options passed to this script: CONFIG_FLAGS="" dnl Keep each token quoted, in case spaces or other special chars crawl in: -_flag_enable_inplace_runtime=no +_flag_enable_inplace_runtime="" for F in "$@" ; do case "$F" in *=*" "*) NF="$(echo "$F" | sed "s,=,=',")""'" && F="$NF" ;; esac case "$F" in - --disable-runtime-support|--enable-runtime-support=no) ;; - --enable-runtime-support*) _flag_enable_inplace_runtime=yes ;; + --disable-runtime-support|--enable-runtime-support=no) _flag_enable_inplace_runtime="no" ;; + --enable-runtime-support*) _flag_enable_inplace_runtime="$F" ;; *) test -z "${CONFIG_FLAGS}" \ && CONFIG_FLAGS="$F" \ @@ -28,12 +28,20 @@ for F in "$@" ; do done dnl Keep it "known" that we tried to re-use at least some local configuration dnl so unspecified options are not necessarily at default values for this script -AS_IF([test x"${_flag_enable_inplace_runtime}" = xyes], [ - F="--enable-runtime-support" - test -z "${CONFIG_FLAGS}" \ - && CONFIG_FLAGS="$F" \ - || CONFIG_FLAGS="${CONFIG_FLAGS} $F" +F="" +AS_CASE(["${_flag_enable_inplace_runtime}"], + [no], [ dnl Explicitly disabled... did we re-enter? Save the value to be seen: + AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x], [ + F="--enable-runtime-support=${NUT_VERSION_DEPLOYED}" ]) + ], + [""], [], + [F="${_flag_enable_inplace_runtime}"]) +AS_IF([test x"$F" != x], [ + test -z "${CONFIG_FLAGS}" \ + && CONFIG_FLAGS="$F" \ + || CONFIG_FLAGS="${CONFIG_FLAGS} $F" + ]) unset _flag_enable_inplace_runtime unset F unset NF @@ -193,6 +201,7 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ SBINDIR="${conftemp}" CONFIG_FLAGS_DEPLOYED="" + NUT_VERSION_DEPLOYED="" dnl TODO: Similar query can be done for BINDIR tools dnl and for libupsclient-config if deployed locally AC_MSG_CHECKING([${SBINDIR}/upsd]) @@ -200,6 +209,10 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ CONFIG_FLAGS_DEPLOYED="`"${SBINDIR}/upsd" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*configured with flags: *,,'`" \ && test x"${CONFIG_FLAGS_DEPLOYED}" != x \ || CONFIG_FLAGS_DEPLOYED="" + + NUT_VERSION_DEPLOYED="`"${SBINDIR}/upsd" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*Network UPS Tools version \(.*\) configured with flags:.*$,\1,'`" \ + && test x"${NUT_VERSION_DEPLOYED}" != x \ + || NUT_VERSION_DEPLOYED="" ]) AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ @@ -207,6 +220,10 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) dnl For multiply-specified flags with conflicting values, last mention wins: AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) + AS_IF([test x"${NUT_VERSION_DEPLOYED}" != x], [ + AC_MSG_NOTICE([NUT_VERSION_DEPLOYED: ${NUT_VERSION_DEPLOYED}]) + export NUT_VERSION_DEPLOYED + ]) eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime ],[ AC_MSG_RESULT([not reported]) From 5da20d2b9e6f7b996bf72cc8b37c067abf87112c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 15:07:40 +0100 Subject: [PATCH 0404/1232] configure.ac: report determining CONFIG_FLAGS [#1709, #1826] --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 1336f62409..15e78967d7 100644 --- a/configure.ac +++ b/configure.ac @@ -8,6 +8,7 @@ dnl in include/nut_version.h (generated by make) AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) dnl Keep track of command-line options passed to this script: +AC_MSG_CHECKING([for CONFIG_FLAGS]) CONFIG_FLAGS="" dnl Keep each token quoted, in case spaces or other special chars crawl in: _flag_enable_inplace_runtime="" @@ -45,6 +46,8 @@ AS_IF([test x"$F" != x], [ unset _flag_enable_inplace_runtime unset F unset NF +AC_MSG_RESULT([${CONFIG_FLAGS}]) + AC_DEFINE_UNQUOTED([CONFIG_FLAGS],["${CONFIG_FLAGS}"],[Flags passed to configure script]) AC_SUBST(CONFIG_FLAGS) From d5140642db6c54af7c0c25201be77bceceeb0f89 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 15:17:04 +0100 Subject: [PATCH 0405/1232] configure.ac: typo fix for CONFIG_FLAGS [#1826] --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 15e78967d7..28d18268a1 100644 --- a/configure.ac +++ b/configure.ac @@ -18,8 +18,8 @@ for F in "$@" ; do esac case "$F" in - --disable-runtime-support|--enable-runtime-support=no) _flag_enable_inplace_runtime="no" ;; - --enable-runtime-support*) _flag_enable_inplace_runtime="$F" ;; + --disable-inplace-runtime|--enable-inplace-runtime=no) _flag_enable_inplace_runtime="no" ;; + --enable-inplace-runtime*) _flag_enable_inplace_runtime="$F" ;; *) test -z "${CONFIG_FLAGS}" \ && CONFIG_FLAGS="$F" \ @@ -33,7 +33,7 @@ F="" AS_CASE(["${_flag_enable_inplace_runtime}"], [no], [ dnl Explicitly disabled... did we re-enter? Save the value to be seen: AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x], [ - F="--enable-runtime-support=${NUT_VERSION_DEPLOYED}" + F="--enable-inplace-runtime='${NUT_VERSION_DEPLOYED}'" ]) ], [""], [], From 236ba23aa7e831f0b628fbaa2763337939115913 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 17:08:39 +0100 Subject: [PATCH 0406/1232] configure.ac: do not pollute "SBINDIR" variable with tests for nut_enable_inplace_runtime, try PATH beside PREFIX, and generalize to try upsc if upsd is not found [#1826] --- configure.ac | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 28d18268a1..bcf8d01a2a 100644 --- a/configure.ac +++ b/configure.ac @@ -194,29 +194,61 @@ NUT_ARG_ENABLE([inplace-runtime], [no]) AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ - AC_MSG_CHECKING([for CONFIG_FLAGS of an already deployed NUT build (if it reports those)]) + AC_MSG_NOTICE([checking for location, CONFIG_FLAGS and version of an already deployed NUT build (if it reports those)]) dnl If existing NUT installation reports its build options, re-run this dnl script with those flags (overridden by any options passed currently): conftemp="${sbindir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" - SBINDIR="${conftemp}" + PREFIX_SBINDIR="${conftemp}" + + conftemp="${bindir}" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + PREFIX_BINDIR="${conftemp}" + + DEPLOYED_SBINDIR="${PREFIX_SBINDIR}" + DEPLOYED_BINDIR="${PREFIX_BINDIR}" + dnl Note use of AC_PATH_PROG for specific pathname (not AC_CHECK_PROGS which picks filename variants)! + dnl Note: "ordinary" users might not have "sbin" in their default PATH, so appending it: + AC_PATH_PROG([DEPLOYED_UPSD], [upsd], [], [${PREFIX_SBINDIR}:${PATH}:/sbin:/usr/sbin:/usr/local/sbin]) + dnl ...however "upsc" is a userland tool so should be there: + AC_PATH_PROG([DEPLOYED_UPSC], [upsc], [], [${PREFIX_BINDIR}:${PATH}]) + AS_IF([test -x "${DEPLOYED_UPSD}"], [DEPLOYED_SBINDIR="`dirname "${DEPLOYED_UPSD}"`"]) + AS_IF([test -x "${DEPLOYED_UPSC}"], [DEPLOYED_BINDIR="`dirname "${DEPLOYED_UPSC}"`"]) + + DEPLOYED_PREFIX="" + AS_IF([test -d "${DEPLOYED_SBINDIR}"], + [DEPLOYED_PREFIX="`dirname "${DEPLOYED_SBINDIR}"`"], + [AS_IF([test -d "${DEPLOYED_BINDIR}"], + [DEPLOYED_PREFIX="`dirname "${DEPLOYED_BINDIR}"`"])] + ) + + AC_MSG_CHECKING([for CONFIG_FLAGS of an already deployed NUT build (if it reports those)]) CONFIG_FLAGS_DEPLOYED="" NUT_VERSION_DEPLOYED="" dnl TODO: Similar query can be done for BINDIR tools dnl and for libupsclient-config if deployed locally - AC_MSG_CHECKING([${SBINDIR}/upsd]) - AS_IF([test -x "${SBINDIR}/upsd"], [ - CONFIG_FLAGS_DEPLOYED="`"${SBINDIR}/upsd" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*configured with flags: *,,'`" \ + for DEPLOYED_TOOL in \ + "${DEPLOYED_UPSD}" \ + "${DEPLOYED_UPSC}" \ + ; do + AS_IF([test x"${DEPLOYED_TOOL}" = x], [continue]) + AS_IF([test -x "${DEPLOYED_TOOL}"], [], [continue]) + + AC_MSG_CHECKING([for CONFIG_FLAGS from ${DEPLOYED_TOOL}]) + CONFIG_FLAGS_DEPLOYED="`"${DEPLOYED_TOOL}" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*configured with flags: *,,'`" \ && test x"${CONFIG_FLAGS_DEPLOYED}" != x \ || CONFIG_FLAGS_DEPLOYED="" - NUT_VERSION_DEPLOYED="`"${SBINDIR}/upsd" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*Network UPS Tools version \(.*\) configured with flags:.*$,\1,'`" \ + NUT_VERSION_DEPLOYED="`"${DEPLOYED_TOOL}" -DV 2>&1 | grep 'configured with flags:' | head -1 | sed 's,^.*Network UPS Tools version \(.*\) configured with flags:.*$,\1,'`" \ && test x"${NUT_VERSION_DEPLOYED}" != x \ || NUT_VERSION_DEPLOYED="" - ]) + + AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}${NUT_VERSION_DEPLOYED}" = x], [], [break]) + done AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ AC_MSG_RESULT([${CONFIG_FLAGS_DEPLOYED}]) From d971f334e9fa1103f0228dd9b25265359f75b241 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 17:43:48 +0100 Subject: [PATCH 0407/1232] configure.ac: set --prefix, --sbindir or --bindir into CONFIG_FLAGS according to older binaries found (if not provided otherwise) [#1826, #1709] --- configure.ac | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/configure.ac b/configure.ac index bcf8d01a2a..75d74edb94 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,28 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}${NUT_VERSION_DEPLOYED}" = x], [], [break]) done + dnl Account for custom paths if known/found: + AS_IF([test x"${DEPLOYED_PREFIX}" != x && test x"${DEPLOYED_PREFIX}" != x"${prefix}"], + AC_MSG_WARN([Deployed NUT installation uses a PREFIX different from one specified (wins) or derived (loses) for this build: '${DEPLOYED_PREFIX}' vs. '${prefix}']) + [AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--prefix=*], [], + [CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --prefix='${DEPLOYED_PREFIX}'"]) + ]) + + AS_IF([test x"${DEPLOYED_SBINDIR}" != x && test x"${DEPLOYED_SBINDIR}" != x"${PREFIX_SBINDIR}"], + AC_MSG_WARN([Deployed NUT installation uses a SBINDIR different from one specified (wins) or derived (loses) for this build: '${DEPLOYED_SBINDIR}' vs. '${sbindir}']) + [AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--sbindir=*], [], + [CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --sbindir='${DEPLOYED_SBINDIR}'"]) + ]) + + AS_IF([test x"${DEPLOYED_BINDIR}" != x && test x"${DEPLOYED_BINDIR}" != x"${PREFIX_BINDIR}"], + AC_MSG_WARN([Deployed NUT installation uses a BINDIR different from one specified (wins) or derived (loses) for this build: '${DEPLOYED_BINDIR}' vs. '${bindir}']) + [AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--bindir=*], [], + [CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --bindir='${DEPLOYED_BINDIR}'"]) + ]) + AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ AC_MSG_RESULT([${CONFIG_FLAGS_DEPLOYED}]) AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) From 2328ba1948e8ff93920812d3b223a4fe898eb29f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 21 Jan 2023 20:50:16 +0100 Subject: [PATCH 0408/1232] configure.ac: fix systemd-tmpfiles detection from AC_CHECK_PROGS to AC_PATH_PROG for full pathname [#1822] --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 374325c2ea..9226059a8b 100644 --- a/configure.ac +++ b/configure.ac @@ -2787,7 +2787,7 @@ fi dnl What pathname would we embed into unit files ExecStartPre? dnl TODO? Any need to make it a --with-... argument? -AC_CHECK_PROGS([SYSTEMD_TMPFILES_PROGRAM], [systemd-tmpfiles], [/usr/bin/systemd-tmpfiles]) +AC_PATH_PROG([SYSTEMD_TMPFILES_PROGRAM], [systemd-tmpfiles], [/usr/bin/systemd-tmpfiles]) dnl Note: we may want binaries with sd_notify and similar features regardless From 1fd0b4617e14e3b34e7647e7f5ca237db7127af5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 12:01:45 +0100 Subject: [PATCH 0409/1232] drivers/libusb1.c: align device_addr/devnum printing (back) with their int types [#1819] --- drivers/libusb1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index d60f316336..2d850a39e1 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -268,12 +268,12 @@ static int nut_libusb_open(libusb_device_handle **udevp, if (devnum <= 999) { /* Log visibly so users know their number discovered * from `lsusb` or `dmesg` (if any) was ignored */ - upsdebugx(0, "%s: invalid libusb device address %i, " - "falling back to enumeration order counter %zd", + upsdebugx(0, "%s: invalid libusb device address %" PRIu8 ", " + "falling back to enumeration order counter %" PRIuSIZE, __func__, device_addr, devnum); sprintf(curDevice->Device, "%03d", (int)devnum); } else { - upsdebugx(1, "%s: invalid libusb device address %i", + upsdebugx(1, "%s: invalid libusb device address %" PRIu8, __func__, device_addr); } } From a67f643d3769d719f946419de4bdc3115dbe989c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 12:13:13 +0100 Subject: [PATCH 0410/1232] tools/nut-scanner/scan_usb.c: sync naming and method changes with drivers/libusb1.c [#1819] --- tools/nut-scanner/scan_usb.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 93b0803922..292c873ede 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -53,7 +53,7 @@ static int (*nut_usb_get_string_simple)(libusb_device_handle *dev, int index, static ssize_t (*nut_usb_get_device_list)(libusb_context *ctx, libusb_device ***list); static void (*nut_usb_free_device_list)(libusb_device **list, int unref_devices); static uint8_t (*nut_usb_get_bus_number)(libusb_device *dev); - static uint8_t (*nut_usb_get_port_number)(libusb_device *dev); + static uint8_t (*nut_usb_get_device_address)(libusb_device *dev); static int (*nut_usb_get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc); #else /* => WITH_LIBUSB_0_1 */ @@ -151,8 +151,8 @@ int nutscan_load_usb_library(const char *libname_path) * was a libusb_get_port_path() equivalent with different arguments, but * not for too long (libusb-1.0.12...1.0.16) and now it is deprecated. */ - *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, - "libusb_get_port_number"); + *(void **) (&nut_usb_get_device_address) = lt_dlsym(dl_handle, + "libusb_get_device_address"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -250,9 +250,12 @@ nutscan_device_t * nutscan_scan_usb() * different consumers plugged into same socket should have * the same port value. However in practice such functionality * depends on platform and HW involved. - * In libusb1 API: libusb_get_port_numbers() earlier known + * In libusb1 API: first libusb_get_port_numbers() earlier known * as libusb_get_port_path() for physical port number on the bus, see * https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html#ga14879a0ea7daccdcddb68852d86c00c4 + * later changed to logical libusb_get_bus_number() (which + * often yields same numeric value, except on systems that + * can not see or tell about physical topology) * In libusb0 API: "device filename" */ char *device_port = NULL; @@ -261,7 +264,7 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 libusb_device *dev; libusb_device **devlist; - uint8_t bus; + uint8_t bus_num; #else /* => WITH_LIBUSB_0_1 */ struct usb_device *dev; struct usb_bus *bus; @@ -310,7 +313,7 @@ nutscan_device_t * nutscan_scan_usb() iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; - bus = (*nut_usb_get_bus_number)(dev); + bus_num = (*nut_usb_get_bus_number)(dev); busname = (char *)malloc(4); if (busname == NULL) { @@ -318,7 +321,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_exit)(NULL); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - snprintf(busname, 4, "%03d", bus); + snprintf(busname, 4, "%03d", bus_num); device_port = (char *)malloc(4); if (device_port == NULL) { @@ -326,9 +329,9 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_exit)(NULL); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } else { - uint8_t port = (*nut_usb_get_port_number)(dev); - if (port > 0) { - snprintf(device_port, 4, "%03d", port); + uint8_t device_addr = (*nut_usb_get_device_address)(dev); + if (device_addr > 0) { + snprintf(device_port, 4, "%03d", device_addr); } else { snprintf(device_port, 4, ".*"); } From bbb07776b6e1c3a6cad0444f0240a9807ba82161 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 12:17:01 +0100 Subject: [PATCH 0411/1232] drivers/libusb1.c: bump version for libusb_get_device_address() vs. libusb_get_port_number() [#1819] --- drivers/libusb1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 2d850a39e1..584d518527 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define USB_DRIVER_NAME "USB communication driver (libusb 1.0)" -#define USB_DRIVER_VERSION "0.44" +#define USB_DRIVER_VERSION "0.45" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { From a4e99da933f87182ba6e946b63cc1bf564abe341 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 12:34:01 +0100 Subject: [PATCH 0412/1232] drivers/richcomm_usb.c, drivers/nutdrv_atcl_usb.c, drivers/bcmxcp_usb.c: sync naming changes with drivers/libusb1.c [#1819, #1763, #1764] --- drivers/bcmxcp_usb.c | 7 ++++--- drivers/nutdrv_atcl_usb.c | 7 ++++--- drivers/richcomm_usb.c | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index b5aeabb52f..9b66aef8e0 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -423,7 +423,8 @@ static usb_dev_handle *open_powerware_usb(void) ssize_t devcount = 0; libusb_device_handle *udev; struct libusb_device_descriptor dev_desc; - uint8_t bus; + uint8_t bus_num; + /* TODO: consider device_addr */ int i; devcount = libusb_get_device_list(NULL, &devlist); @@ -441,13 +442,13 @@ static usb_dev_handle *open_powerware_usb(void) curDevice.VendorID = dev_desc.idVendor; curDevice.ProductID = dev_desc.idProduct; - bus = libusb_get_bus_number(device); + bus_num = libusb_get_bus_number(device); curDevice.Bus = (char *)malloc(4); if (curDevice.Bus == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - sprintf(curDevice.Bus, "%03d", bus); + sprintf(curDevice.Bus, "%03d", bus_num); /* FIXME: we should also retrieve * dev->descriptor.iManufacturer diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index b515c25ef2..f88d4c6a85 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -283,7 +283,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev ssize_t devcount = 0; libusb_device_handle *handle; struct libusb_device_descriptor dev_desc; - uint8_t bus; + uint8_t bus_num; + /* TODO: consider device_addr */ int i; devcount = libusb_get_device_list(NULL, &devlist); @@ -341,13 +342,13 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #if WITH_LIBUSB_1_0 device->VendorID = dev_desc.idVendor; device->ProductID = dev_desc.idProduct; - bus = libusb_get_bus_number(dev); + bus_num = libusb_get_bus_number(dev); device->Bus = (char *)malloc(4); if (device->Bus == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - sprintf(device->Bus, "%03d", bus); + sprintf(device->Bus, "%03d", bus_num); iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 3df85f2449..42dff8953c 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -332,7 +332,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev ssize_t devcount = 0; libusb_device_handle *handle; struct libusb_device_descriptor dev_desc; - uint8_t bus; + uint8_t bus_num; + /* TODO: consider device_addr */ int i; devcount = libusb_get_device_list(NULL, &devlist); @@ -391,13 +392,13 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #if WITH_LIBUSB_1_0 device->VendorID = dev_desc.idVendor; device->ProductID = dev_desc.idProduct; - bus = libusb_get_bus_number(dev); + bus_num = libusb_get_bus_number(dev); device->Bus = (char *)malloc(4); if (device->Bus == NULL) { libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - sprintf(device->Bus, "%03d", bus); + sprintf(device->Bus, "%03d", bus_num); iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; From 863f2fc59c9702114ae0a269faafd5bd0cde5713 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:11:21 +0100 Subject: [PATCH 0413/1232] m4/nut_report_feature.m4: standardize indentation, more M4 AS_IFs [#1826] --- m4/nut_report_feature.m4 | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index dbe4455a29..31814c2ce2 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -10,10 +10,10 @@ AC_DEFUN([NUT_REPORT_FILE], dnl arg#2 = value dnl arg#3 = file tag (e.g. number) dnl arg#4 = file title (e.g. "NUT Configuration summary:") - if test -z "${nut_report_feature_flag$3}"; then + AS_IF([test x"${nut_report_feature_flag$3}" = x], [ nut_report_feature_flag$3="1" ac_clean_files="${ac_clean_files} config.nut_report_feature.log.$3" - if test x1 = x$3 ; then + if test x1 = "x$3" ; then echo "$4" echo "$4" | sed 's/./=/g' echo "" @@ -23,7 +23,7 @@ AC_DEFUN([NUT_REPORT_FILE], echo "$4" | sed 's/./-/g' echo "" fi > "config.nut_report_feature.log.$3" - fi + ]) printf "* $1:\t$2\n" >> "config.nut_report_feature.log.$3" ]) @@ -55,14 +55,14 @@ AC_DEFUN([NUT_REPORT_FEATURE], dnl arg#3 = value dnl arg#4 = autoconf varname dnl arg#5 = longer description (autoconf comment) - AC_MSG_CHECKING([whether to $1]) - AC_MSG_RESULT([$2 $3]) - NUT_REPORT([$1], [$2 $3]) - - AM_CONDITIONAL([$4], test "$2" = "yes") - if test "$2" = "yes"; then - AC_DEFINE_UNQUOTED($4, 1, $5) - fi + AC_MSG_CHECKING([whether to $1]) + AC_MSG_RESULT([$2 $3]) + NUT_REPORT([$1], [$2 $3]) + + AM_CONDITIONAL([$4], test "$2" = "yes") + AS_IF([test x"$2" = x"yes"], [ + AC_DEFINE_UNQUOTED($4, 1, $5) + ]) ]) AC_DEFUN([NUT_REPORT_SETTING], @@ -71,12 +71,12 @@ AC_DEFUN([NUT_REPORT_SETTING], dnl arg#2 = autoconf varname dnl arg#3 = value dnl arg#4 = longer description (autoconf comment) - AC_MSG_CHECKING([setting for $1]) - AC_MSG_RESULT([$3]) - NUT_REPORT([$1], [$3]) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT([$1], [$3]) - dnl Note: unlike features, settings do not imply an AutoMake toggle - AC_DEFINE_UNQUOTED($2, $3, $4) + dnl Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) ]) AC_DEFUN([NUT_REPORT_SETTING_PATH], @@ -85,12 +85,12 @@ AC_DEFUN([NUT_REPORT_SETTING_PATH], dnl arg#2 = autoconf varname dnl arg#3 = value dnl arg#4 = longer description (autoconf comment) - AC_MSG_CHECKING([setting for $1]) - AC_MSG_RESULT([$3]) - NUT_REPORT_PATH([$1], [$3]) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT_PATH([$1], [$3]) - dnl Note: unlike features, settings do not imply an AutoMake toggle - AC_DEFINE_UNQUOTED($2, $3, $4) + dnl Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) ]) AC_DEFUN([NUT_REPORT_SETTING_PATH_INTEGRATIONS], @@ -99,12 +99,12 @@ AC_DEFUN([NUT_REPORT_SETTING_PATH_INTEGRATIONS], dnl arg#2 = autoconf varname dnl arg#3 = value dnl arg#4 = longer description (autoconf comment) - AC_MSG_CHECKING([setting for $1]) - AC_MSG_RESULT([$3]) - NUT_REPORT_PATH_INTEGRATIONS([$1], [$3]) + AC_MSG_CHECKING([setting for $1]) + AC_MSG_RESULT([$3]) + NUT_REPORT_PATH_INTEGRATIONS([$1], [$3]) - dnl Note: unlike features, settings do not imply an AutoMake toggle - AC_DEFINE_UNQUOTED($2, $3, $4) + dnl Note: unlike features, settings do not imply an AutoMake toggle + AC_DEFINE_UNQUOTED($2, $3, $4) ]) AC_DEFUN([NUT_REPORT_TARGET], @@ -122,18 +122,18 @@ AC_DEFUN([NUT_REPORT_TARGET], AC_DEFUN([NUT_REPORT_COMPILERS], [ - (echo "" - echo "NUT Compiler settings:" - echo "----------------------" - echo "" - printf '* CC \t: %s\n' "$CC" - printf '* CFLAGS \t: %s\n' "$CFLAGS" - printf '* CXX \t: %s\n' "$CXX" - printf '* CXXFLAGS\t: %s\n' "$CXXFLAGS" - printf '* CPP \t: %s\n' "$CPP" - printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" - printf '* CONFIG_FLAGS\t: %s\n' "$CONFIG_FLAGS" - ) > config.nut_report_feature.log.9 + (echo "" + echo "NUT Compiler settings:" + echo "----------------------" + echo "" + printf '* CC \t: %s\n' "$CC" + printf '* CFLAGS \t: %s\n' "$CFLAGS" + printf '* CXX \t: %s\n' "$CXX" + printf '* CXXFLAGS\t: %s\n' "$CXXFLAGS" + printf '* CPP \t: %s\n' "$CPP" + printf '* CPPFLAGS\t: %s\n' "$CPPFLAGS" + printf '* CONFIG_FLAGS\t: %s\n' "$CONFIG_FLAGS" + ) > config.nut_report_feature.log.9 ac_clean_files="${ac_clean_files} config.nut_report_feature.log.9" ]) From a1dacb28029a9a9eaf9d1efdbf55a115219dc5d7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:17:07 +0100 Subject: [PATCH 0414/1232] m4/nut_report_feature.m4, Makefile.am: install config.nut_report_feature.log if kept [#1826] --- Makefile.am | 4 ++++ m4/nut_report_feature.m4 | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Makefile.am b/Makefile.am index 7b87c013ba..15c04d411e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,6 +27,10 @@ EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING # want to adapt it to their autotools or locally fix a tarball-based build. EXTRA_DIST += autogen.sh +if KEEP_NUT_REPORT +nodist_data_DATA = config.nut_report_feature.log +endif + # ---------------------------------------------------------------------- # flags to pass to ./configure when calling "make distcheck" and "make # distcheck-light". Try to check as many features as possible! Also diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 31814c2ce2..29b98eda8f 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -152,4 +152,6 @@ AC_DEFUN([NUT_PRINT_FEATURE_REPORT], ac_clean_files="${ac_clean_files} config.nut_report_feature.log" cat config.nut_report_feature.log.* ]) + + AM_CONDITIONAL(KEEP_NUT_REPORT, test x"${nut_enable_keep_nut_report_feature-}" = xyes) ]) From a8781a418b121a96fa8303c48d708224f5f72031 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:27:44 +0100 Subject: [PATCH 0415/1232] configure.ac: report GITREV (if any) valid at the time of configure run --- configure.ac | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b2fbd1f095..834aaf0569 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,14 @@ dnl NUT_VERSION_MACRO "2.7.4-2838-gdfc3ac08" dnl in include/nut_version.h (generated by make) AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) +dnl Note: this refers to GITREV at the time of configure script running +dnl primarily for better messaging in the script itself. +dnl If the NUT codebase in this workspace is being developed and rebuilt +dnl without reconfiguration, detailed version in the binaries will differ. +(command -v git >/dev/null 2>/dev/null) \ +&& GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +|| GITREV="" + dnl Keep track of command-line options passed to this script: AC_MSG_CHECKING([for CONFIG_FLAGS]) CONFIG_FLAGS="" @@ -54,7 +62,9 @@ AC_SUBST(CONFIG_FLAGS) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_SRCDIR(server/upsd.c) AC_CONFIG_MACRO_DIR([m4]) -echo "Network UPS Tools version ${PACKAGE_VERSION}" +AS_IF([test x"${GITREV}" = x], + [echo "Network UPS Tools version ${PACKAGE_VERSION}"], + [echo "Network UPS Tools version ${PACKAGE_VERSION} (${GITREV})"]) AC_CANONICAL_TARGET NUT_CHECK_OS NUT_STASH_WARNINGS From 4c1cef914889c1bb30fd81df59f696a15bf35dd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:28:18 +0100 Subject: [PATCH 0416/1232] configure.ac: NUT_REPORT() the PACKAGE_VERSION (and GITREV if any) valid at the time of configure run [#1826] --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 834aaf0569..ed7a2f87f6 100644 --- a/configure.ac +++ b/configure.ac @@ -368,6 +368,11 @@ AC_C_VARARRAYS NUT_ARG_ENABLE([keep_nut_report_feature], [Request that we keep config.nut_report_feature.log (normally deleted by configure script after displaying)], [no]) + +AS_IF([test x"${GITREV}" = x], + [NUT_REPORT([configured version], [${PACKAGE_VERSION}])], + [NUT_REPORT([configured version], [${PACKAGE_VERSION} (${GITREV})])]) + dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase: NUT_COMPILER_FAMILY dnl Help find warning/error details in a wall of text (must be processed before NUT_COMPILER_FAMILY_FLAGS): From 9744922c784ed1e41b7ace1093c5b2e6136d4dc5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:36:46 +0100 Subject: [PATCH 0417/1232] docs/configure.txt: document --enable-keep_nut_report_feature and that the file can be installed [#1826] --- docs/configure.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/configure.txt b/docs/configure.txt index 138bae9142..ffb3162e0c 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -41,6 +41,15 @@ Network UPS Tools upsd 2.8.0.1 A more industrial approach is to use `lib/libupsclient-config --config-flags` where supported. +Keeping a report of NUT configuration +------------------------------------- + + --enable-keep_nut_report_feature + +If this option is enabled (not currently default), the report displayed +by `configure` script will be kept in a file when the script ends, and +installed into the data directory. + In-place replacement defaults ----------------------------- @@ -65,6 +74,10 @@ If the installed NUT version supports reporting of `CONFIG_FLAGS` used during its build, the `configure` script will try to take those values into account when running in this mode. +NOTE: This does not currently rely on the configuration report optionally +installed by `--enable-keep_nut_report_feature` above, but might do so +eventually. + Driver selection ---------------- From dc441e616a8ac321b5e21a8f4416c1d9dc1a0587 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:37:21 +0100 Subject: [PATCH 0418/1232] docs/configure.txt: debug-report of CONFIG_FLAGS is now shorter --- docs/configure.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure.txt b/docs/configure.txt index ffb3162e0c..e5a93ea505 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -35,7 +35,7 @@ to produce a replacement by asking NUT programs for `--help` or for ---- :; upsd -DV Network UPS Tools upsd 2.8.0.1 - 0.000000 [D1] Network UPS Tools version 2.8.0.1 configured with flags: --with-all=auto --with-doc=skip ... +Network UPS Tools version 2.8.0.1 configured with flags: --with-all=auto --with-doc=skip ... ---- A more industrial approach is to use `lib/libupsclient-config --config-flags` From e6912da1243a10b60f0c7f74592a937f1ec577ab Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 18:40:32 +0100 Subject: [PATCH 0419/1232] UPGRADING: document --enable-keep_nut_report_feature and that the file can be installed [#1826, #1708] --- UPGRADING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UPGRADING b/UPGRADING index b724e8173b..47bc73c3a1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -79,6 +79,11 @@ Changes from 2.8.0 to 2.8.1 to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] +- The "layman report" of NUT configuration options displayed after the run + of `configure` script can now be retained and installed by using the + `--enable-keep_nut_report_feature` option; packagers are welcome to make + use of this, to better keep track of their deliveries [#1826, #1708] + - Renamed generated nut-common.tmpfiles(.in) => nut-common-tmpfiles.conf(.in) to install a /usr/lib/systemd-tmpfiles/*.conf pattern [#1755] From f14bbcfb3544af18ec54ca0aa7f4486b77de6868 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 21:29:29 +0100 Subject: [PATCH 0420/1232] configure.ac, m4/nut_report_feature.m4: move KEEP_NUT_REPORT definition to before AC_OUTPUT [#1826] --- configure.ac | 3 +++ m4/nut_report_feature.m4 | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index ed7a2f87f6..feff0c000b 100644 --- a/configure.ac +++ b/configure.ac @@ -4121,6 +4121,9 @@ m4_foreach_w([SCRIPTFILE], [ ) ]) +dnl Define this before AC_OUTPUT(), so not in report below +AM_CONDITIONAL(KEEP_NUT_REPORT, test x"${nut_enable_keep_nut_report_feature-}" = xyes) + AC_OUTPUT NUT_REPORT_COMPILERS diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 29b98eda8f..31814c2ce2 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -152,6 +152,4 @@ AC_DEFUN([NUT_PRINT_FEATURE_REPORT], ac_clean_files="${ac_clean_files} config.nut_report_feature.log" cat config.nut_report_feature.log.* ]) - - AM_CONDITIONAL(KEEP_NUT_REPORT, test x"${nut_enable_keep_nut_report_feature-}" = xyes) ]) From 3854c3f2736759a454cf83c350a94f4e3d14ec5a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 22:07:23 +0100 Subject: [PATCH 0421/1232] docs/config-prereqs.txt: suggest MKDIRPROG hack for installing on NetBSD [#1834] --- docs/config-prereqs.txt | 7 ++++++- docs/nut.dict | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 1dd555216e..19233af448 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -730,10 +730,15 @@ as detailed below: :; export PATH ------ -To use the `ci_build.sh` don't forget `bash` which is not part of OpenBSD +To use the `ci_build.sh` don't forget `bash` which may be not part of NetBSD base installation. It is not required for "legacy" builds arranged by just `autogen.sh` and `configure` scripts. +Also note that the `install-sh` helper added by autotools from OS-provided +resources when generating the `configure` script may be old and its directory +creation mode is not safe for parallel-`make` installations. If this happens, +you can work around by `make MKDIRPROG="mkdir -p" install -j 8` for example. + ------ :; pkgin install \ git python27 python39 perl curl \ diff --git a/docs/nut.dict b/docs/nut.dict index 8fb2e88371..7223daa387 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3087 utf-8 +personal_ws-1.1 en 3088 utf-8 AAS ABI ACFAIL @@ -636,6 +636,7 @@ MIBs MINLINEV MINSUPPLIES MINTIMEL +MKDIRPROG MLH MMM MMMMMMMMMMMMMMM From 852e76b45a95df7ef2e3cf521b6aaf81be0b5811 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 22:21:44 +0100 Subject: [PATCH 0422/1232] ci_build.sh: help find end of NUT_x_VARIANT=... failed build (before cleanup noise) in CI logs --- ci_build.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index bbf4207e1f..ed18540330 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1524,6 +1524,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp } || { RES_ALLERRORS=$? FAILED="${FAILED} NUT_SSL_VARIANT=${NUT_SSL_VARIANT}[build]" + # Help find end of build (before cleanup noise) in logs: + echo "=== FAILED 'NUT_SSL_VARIANT=${NUT_SSL_VARIANT}' build" if [ "$CI_FAILFAST" = true ]; then echo "===== Aborting because CI_FAILFAST=$CI_FAILFAST" >&2 break @@ -1658,6 +1660,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp } || { RES_ALLERRORS=$? FAILED="${FAILED} NUT_USB_VARIANT=${NUT_USB_VARIANT}[build]" + # Help find end of build (before cleanup noise) in logs: + echo "=== FAILED 'NUT_USB_VARIANT=${NUT_USB_VARIANT}' build" if [ "$CI_FAILFAST" = true ]; then echo "===== Aborting because CI_FAILFAST=$CI_FAILFAST" >&2 break From 13c08db4ce8f5f95ee3c589ff039766b477ca2e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 10:58:57 +0100 Subject: [PATCH 0423/1232] scripts/hotplug/Makefile.am: fix EXTRA_DIST for libhid.usermap [#1831] --- scripts/hotplug/Makefile.am | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/hotplug/Makefile.am b/scripts/hotplug/Makefile.am index 06a6fe3116..6595084913 100644 --- a/scripts/hotplug/Makefile.am +++ b/scripts/hotplug/Makefile.am @@ -1,20 +1,21 @@ +EXTRA_DIST = README if WITH_HOTPLUG hotplugusbdir = $(hotplugdir)/usb dist_hotplugusb_DATA = libhid.usermap hotplugusb_SCRIPTS = libhidups +else + # Part of dist tarball, regardless of use for current build: + EXTRA_DIST += libhid.usermap endif -EXTRA_DIST = README - MAINTAINERCLEANFILES = Makefile.in .dirstamp # Generated by configure script: DISTCLEANFILES = libhidups -# we should never remove this one, apart from a distclean-check -#MAINTAINERCLEANFILES = libhid.usermap - +# We should never remove this one, apart from a distclean-check +# or stronger... # Generated by autogen.sh and needed to run the configure script # (technically, generated by tools/nut-usbinfo.pl script among # GENERATED_USB_OS_FILES): From f1e78fe2e6653f9aedf3173430938f746a8fb631 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 11:09:11 +0100 Subject: [PATCH 0424/1232] scripts/udev/Makefile.am: fix EXTRA_DIST for nut-usbups.rules.in [#1831] --- scripts/udev/Makefile.am | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/udev/Makefile.am b/scripts/udev/Makefile.am index 5d299a711d..f84e4c1fe5 100644 --- a/scripts/udev/Makefile.am +++ b/scripts/udev/Makefile.am @@ -25,10 +25,12 @@ DISTCLEANFILES = nut-usbups.rules nut-ipmipsu.rules CLEANFILES = 62-nut-usbups.rules 52-nut-ipmipsu.rules -# we should never remove this one, apart from a distclean-check -#MAINTAINERCLEANFILES = nut-usbups.rules.in - +# We should never remove this one, apart from a distclean-check +# or stronger... # Generated by autogen.sh and needed to run the configure script # (technically, generated by tools/nut-usbinfo.pl script among # GENERATED_USB_OS_FILES): MAINTAINERCLEANFILES += nut-usbups.rules.in nut-usbups.rules.in.AUTOGEN_WITHOUT + +# Part of dist tarball, regardless of use for current build: +EXTRA_DIST += nut-usbups.rules.in From 2961d1842dc262b1ef18f2bf844d250829afd58f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 11:11:10 +0100 Subject: [PATCH 0425/1232] scripts/devd/Makefile.am: fix EXTRA_DIST for nut-usb.conf.in [#1831] --- scripts/devd/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/devd/Makefile.am b/scripts/devd/Makefile.am index c1c8097411..72a9031aab 100644 --- a/scripts/devd/Makefile.am +++ b/scripts/devd/Makefile.am @@ -15,12 +15,12 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp DISTCLEANFILES = nut-usb.conf # we should never remove this one, apart from a distclean-check -#MAINTAINERCLEANFILES = nut-usbups.rules.in - +# or stronger... # Generated by autogen.sh and needed to run the configure script # (technically, generated by tools/nut-usbinfo.pl script among # GENERATED_USB_OS_FILES): -MAINTAINERCLEANFILES += nut-usbups.rules.in -MAINTAINERCLEANFILES += nut-usbups.rules.in.AUTOGEN_WITHOUT MAINTAINERCLEANFILES += nut-usb.conf.in MAINTAINERCLEANFILES += nut-usb.conf.in.AUTOGEN_WITHOUT + +# Part of dist tarball, regardless of use for current build: +EXTRA_DIST += nut-usb.conf.in From f41dcc514784c9b49d0d3ae4a73f070b238c2c0f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 11:18:43 +0100 Subject: [PATCH 0426/1232] scripts/Makefile.am: fix EXTRA_DIST for upower/95-upower-hid.hwdb [#1831] --- scripts/Makefile.am | 1 + tools/Makefile.am | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 893d90039e..c87559b597 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = README \ subdriver/gen-usbhid-subdriver.sh \ subdriver/gen-snmp-subdriver.sh \ ufw/README \ + upower/95-upower-hid.hwdb \ upower/95-upower-hid.rules \ Windows/halt.c \ Windows/Makefile diff --git a/tools/Makefile.am b/tools/Makefile.am index 49af8d9153..6b15b49f65 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,7 +30,8 @@ GENERATED_USB_OS_FILES += ../scripts/udev/nut-usbups.rules.in GENERATED_USB_OS_FILES += ../scripts/devd/nut-usb.conf.in # UPower output file -GENERATED_USB_OS_FILES += ../scripts/upower/95-upower-hid.rules +# Note: unlike others above, this one is currently tracked in Git +GENERATED_USB_OS_FILES += ../scripts/upower/95-upower-hid.hwdb CLEANFILES = $(GENERATED_SNMP_FILES) $(GENERATED_USB_FILES) # We do not clean away these files, some are even tracked in Git: From dcab09cf9aafd861f6d5c0170e5a5d0b717b4879 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 11:32:14 +0100 Subject: [PATCH 0427/1232] scripts/augeas/Makefile.am: fix EXTRA_DIST for nutupsconf.aug.in [#1831] --- scripts/augeas/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/augeas/Makefile.am b/scripts/augeas/Makefile.am index 247a68e58d..46282e869f 100644 --- a/scripts/augeas/Makefile.am +++ b/scripts/augeas/Makefile.am @@ -46,4 +46,7 @@ DISTCLEANFILES = gen-nutupsconf-aug.py # Generated by autogen.sh and needed to run the configure script: MAINTAINERCLEANFILES += nutupsconf.aug.in nutupsconf.aug.in.AUTOGEN_WITHOUT +# Part of dist tarball, regardless of use for current build: +EXTRA_DIST += nutupsconf.aug.in + DISTCLEANFILES += *.aug From 5e5ee35511e686264f1289d8711a9407e2a03ea7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 11:46:29 +0100 Subject: [PATCH 0428/1232] tools/Makefile.am: comment GENERATED_SNMP_FILES+GENERATED_USB_FILES vs. GENERATED_USB_OS_FILES lifecycles [#1831] --- tools/Makefile.am | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/Makefile.am b/tools/Makefile.am index 6b15b49f65..3bc5d10a55 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -16,10 +16,22 @@ PYTHON = @PYTHON@ EXTRA_DIST = nut-usbinfo.pl nut-recorder.sh nut-ddl-dump.sh nut-dumpdiff.sh \ gitlog2changelog.py.in nut-snmpinfo.py.in driver-list-format.sh +# These files are generated for nut-scanner builds (and cleaned as any others), +# and can change as respective SNMP/USB subdriver sources are iterated by a +# locally active developer: GENERATED_SNMP_FILES = nut-scanner/nutscan-snmp.h GENERATED_USB_FILES = nut-scanner/nutscan-usb.h +# These files for OS integration are generated by `autogen.sh` and distributed +# by a release tarball (and not normally cleaned away). While technically their +# contents can change as respective USB subdriver sources are iterated by a +# locally active developer (especially changing supported VID:PID combinations), +# this is not a requirement that would block local re-builds nor a frequent +# use case. So they are not normally rebuilt intentionally (could be anyway, +# as part of nut-scanner dependency re-generations), and for install/release +# after such fundamental changes the project should better run `autogen.sh`. + # Hotplug output file GENERATED_USB_OS_FILES = ../scripts/hotplug/libhid.usermap From b7d7c0ccf17c1a21731c37a1364fe7aa2a6e58e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 16:51:07 +0100 Subject: [PATCH 0429/1232] tools/Makefile.am: streamline "rebuilds" of GENERATED_USB_OS_FILES if needed [#1831] An alternative solution to #1832 --- tools/Makefile.am | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/Makefile.am b/tools/Makefile.am index 3bc5d10a55..3508e91e84 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -73,6 +73,16 @@ $(GENERATED_SNMP_FILES): $(top_srcdir)/drivers/*-mib.c echo "----------------------------------------------------------------------"; \ fi +# Currently GENERATED_USB_FILES refers to a single file, which ensures +# that the perl script (if needed) runs once even in parallel builds. +# The GENERATED_USB_OS_FILES should not *have* to be built by make at +# all, but just in case (developer iterations) a dependency is here. +# It is expected that the files exist (from tarball or latest run of +# script for GENERATED_USB_FILES purposes), so we only confirm that +# and bump timestamps to avoid more noise. +$(GENERATED_USB_OS_FILES): $(GENERATED_USB_FILES) + @test -s "$@" && touch "$@" + $(GENERATED_USB_FILES): $(top_srcdir)/drivers/*-hid.c $(top_srcdir)/drivers/*usb*.c $(top_srcdir)/drivers/nutdrv_qx.c @if perl -e 1; then \ echo "Regenerating the USB helper files in SRC dir."; \ From 3187cc8d91010c2adacfd60eadabd893f2352d0d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 17:19:36 +0100 Subject: [PATCH 0430/1232] autogen.sh: ensure that nut-usbinfo.pl runs if any of its products are missing, not just a few (and comment how to keep the list updated) [#1831] --- autogen.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index c591f9dbed..bf9316afb9 100755 --- a/autogen.sh +++ b/autogen.sh @@ -71,8 +71,16 @@ then fi fi +# Keep in sync with tools/nut-usbinfo.pl outputs: +# * List actual file opens: +# grep -i '">' tools/nut-usbinfo.pl +# * List the names involved: +# grep -E 'output.*=' tools/nut-usbinfo.pl if [ ! -f scripts/udev/nut-usbups.rules.in -o \ - ! -f scripts/devd/nut-usb.conf.in ] + ! -f scripts/hotplug/libhid.usermap -o \ + ! -f scripts/upower/95-upower-hid.hwdb -o \ + ! -f scripts/devd/nut-usb.conf.in -o \ + ! -f tools/nut-scanner/nutscan-usb.h ] then if perl -e 1; then echo "Regenerating the USB helper files..." From fd871a22e943fb1b1a87b0a295670e67dc5f60f6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 17:27:53 +0100 Subject: [PATCH 0431/1232] tools/Makefile.am: do not fail (just warn) if any of GENERATED_USB_OS_FILES are missing or empty [#1831] --- tools/Makefile.am | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index 3508e91e84..0a2841e32f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -79,9 +79,13 @@ $(GENERATED_SNMP_FILES): $(top_srcdir)/drivers/*-mib.c # all, but just in case (developer iterations) a dependency is here. # It is expected that the files exist (from tarball or latest run of # script for GENERATED_USB_FILES purposes), so we only confirm that -# and bump timestamps to avoid more noise. +# and bump their timestamps to avoid more noise. Note that for some +# builds from scratch (with explicit envvars passed to autogen.sh) +# these files may be empty to satisfy dependencies and forfeit the +# features for a particular build. $(GENERATED_USB_OS_FILES): $(GENERATED_USB_FILES) - @test -s "$@" && touch "$@" + @test -s "$@" || echo "WARNING: GENERATED_USB_OS_FILES: '$@' is empty or missing; do not use this build to generate 'dist' tarballs" >&2 + @touch "$@" $(GENERATED_USB_FILES): $(top_srcdir)/drivers/*-hid.c $(top_srcdir)/drivers/*usb*.c $(top_srcdir)/drivers/nutdrv_qx.c @if perl -e 1; then \ From c65384b001772d0392e8b87bc65c2bce3dc97927 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 22:48:15 +0100 Subject: [PATCH 0432/1232] */Makefile.am: replace "mkdir -p" by MKDIR_P autotools macro --- docs/Makefile.am | 2 +- docs/man/Makefile.am | 2 +- scripts/Solaris/Makefile.am | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 327c1bb0fd..f602ce4d64 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -201,7 +201,7 @@ DOCBUILD_BEGIN = { \ if test -n "$${A2X_OUTDIR}" && test "$${A2X_OUTDIR}" != '.' ; then \ rm -rf "./$${A2X_OUTDIR}" || true ; \ test -d "$@" && rm -rf "$@" || true ; \ - mkdir -p "./$${A2X_OUTDIR}" || exit ; \ + $(MKDIR_P) "./$${A2X_OUTDIR}" || exit ; \ case "$${A2X_OUTDIR}" in \ tmp/pdf.*) ln -s ../../images "./$${A2X_OUTDIR}" ;; \ esac; \ diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index b11465d1b2..53ab88017e 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -901,7 +901,7 @@ DOCBUILD_BEGIN = { \ if test -n "$${A2X_OUTDIR}" && test "$${A2X_OUTDIR}" != '.' ; then \ rm -rf "./$${A2X_OUTDIR}" || true ; \ test -d "$@" && rm -rf "$@" || true ; \ - mkdir -p "./$${A2X_OUTDIR}" || exit ; \ + $(MKDIR_P) "./$${A2X_OUTDIR}" || exit ; \ for F in $(LINKMAN_INCLUDE_GENERATED) ; do \ if [ -s "./$$F" ] ; then ln -f -s "../../$$F" "./$${A2X_OUTDIR}/" ; else \ if [ -s "$(abs_srcdir)/$$F" ] ; then ln -f -s "$(abs_srcdir)/$$F" "./$${A2X_OUTDIR}/" ; fi ; fi ; \ diff --git a/scripts/Solaris/Makefile.am b/scripts/Solaris/Makefile.am index 20b3694402..678b4eb8e6 100644 --- a/scripts/Solaris/Makefile.am +++ b/scripts/Solaris/Makefile.am @@ -58,7 +58,7 @@ SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS = preinstall postinstall preremove postremov SOLARIS_PACKAGE_SVR4_INSTALLDATA = pkginfo package-solaris-svr4: $(SOLARIS_PACKAGE_SVR4_HELPERSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLDATA) if test -n "@auglensdir@" && test -d "$(DESTDIR)@auglensdir@" ; then \ - mkdir -p "$(DESTDIR)@datadir@/augeas-lenses" && \ + $(MKDIR_P) "$(DESTDIR)@datadir@/augeas-lenses" && \ cd "$(DESTDIR)@auglensdir@" && \ ( cp -prf ./ "$(DESTDIR)@datadir@/augeas-lenses/" || cp -rf ./ "$(DESTDIR)@datadir@/augeas-lenses/" ) ; fi cd $(PROTOTYPE_DIR) && find . -print | pkgproto > prototype1 From 2ce30fc573ebea63ad0ab1fa40f25f4db07f5377 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 22:46:55 +0100 Subject: [PATCH 0433/1232] tools/Makefile.am: give delivery of GENERATED_USB_OS_FILES more chances to succeed --- tools/Makefile.am | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index 0a2841e32f..bc3d255202 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -33,17 +33,17 @@ GENERATED_USB_FILES = nut-scanner/nutscan-usb.h # after such fundamental changes the project should better run `autogen.sh`. # Hotplug output file -GENERATED_USB_OS_FILES = ../scripts/hotplug/libhid.usermap +GENERATED_USB_OS_FILES = $(top_builddir)/scripts/hotplug/libhid.usermap # udev output file -GENERATED_USB_OS_FILES += ../scripts/udev/nut-usbups.rules.in +GENERATED_USB_OS_FILES += $(top_builddir)/scripts/udev/nut-usbups.rules.in # BSD devd output file -GENERATED_USB_OS_FILES += ../scripts/devd/nut-usb.conf.in +GENERATED_USB_OS_FILES += $(top_builddir)/scripts/devd/nut-usb.conf.in # UPower output file # Note: unlike others above, this one is currently tracked in Git -GENERATED_USB_OS_FILES += ../scripts/upower/95-upower-hid.hwdb +GENERATED_USB_OS_FILES += $(top_builddir)/scripts/upower/95-upower-hid.hwdb CLEANFILES = $(GENERATED_SNMP_FILES) $(GENERATED_USB_FILES) # We do not clean away these files, some are even tracked in Git: @@ -83,8 +83,22 @@ $(GENERATED_SNMP_FILES): $(top_srcdir)/drivers/*-mib.c # builds from scratch (with explicit envvars passed to autogen.sh) # these files may be empty to satisfy dependencies and forfeit the # features for a particular build. +# To facilitate "make distcheck" and out-of-tree builds, we try to +# use files pre-generated in SRCDIR if those in BUILDDIR dir are empty +# or did not appear. $(GENERATED_USB_OS_FILES): $(GENERATED_USB_FILES) @test -s "$@" || echo "WARNING: GENERATED_USB_OS_FILES: '$@' is empty or missing; do not use this build to generate 'dist' tarballs" >&2 + @$(MKDIR_P) "$(@D)" + @if ! test -s "$@" ; then \ + if test x"$(top_srcdir)" != x"$(top_builddir)" ; then \ + RELNAME="`echo "$@" | sed 's,^$(top_builddir)/*,,'`" ; \ + SRCNAME="$(top_srcdir)/$${RELNAME}" ; \ + if test -s "$${SRCNAME}" ; then \ + echo "WARNING: GENERATED_USB_OS_FILES: using '$${SRCNAME}' for '$@'" >&2 ; \ + cp "$${SRCNAME}" "$@" ; \ + fi ; \ + fi ; \ + fi @touch "$@" $(GENERATED_USB_FILES): $(top_srcdir)/drivers/*-hid.c $(top_srcdir)/drivers/*usb*.c $(top_srcdir)/drivers/nutdrv_qx.c From c14ad29547df263d4163f26c002db10c92c3a29d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 23 Jan 2023 18:06:44 +0100 Subject: [PATCH 0434/1232] configure.ac: suggest workarounds for old and broken install-sh, visibly just before the end [#1831] --- configure.ac | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index feff0c000b..c0658fd7f1 100644 --- a/configure.ac +++ b/configure.ac @@ -4121,10 +4121,20 @@ m4_foreach_w([SCRIPTFILE], [ ) ]) -dnl Define this before AC_OUTPUT(), so not in report below +dnl Define this before AC_OUTPUT(), so not inside the report routine below: AM_CONDITIONAL(KEEP_NUT_REPORT, test x"${nut_enable_keep_nut_report_feature-}" = xyes) +dnl Prints a long list of files generated from templates... AC_OUTPUT +dnl Normally the latest action, for the summary to be visible: NUT_REPORT_COMPILERS NUT_PRINT_FEATURE_REPORT + +dnl Stopping short of patching the unknown script, we can warn about the issue +dnl (visibly as it impacts next activities of the caller): +AS_IF([test -s "${ABS_TOP_SRCDIR}/install-sh" && (grep -w MKDIRPROG "${ABS_TOP_SRCDIR}/install-sh" && { grep -v '#' "${ABS_TOP_SRCDIR}/install-sh" | grep -E '\$mkdirprog.*-p' ; } ; ) >/dev/null], + [AC_MSG_WARN([Your system provided (or NUT tarball included) an 'install-sh' implementation]) + AC_MSG_WARN([which is not safe for parallel installs; export MKDIRPROG='mkdir -p' may help,]) + AC_MSG_WARN([otherwise run 'make install' sequentially. It should not impact parallel builds.]) + ]) From 34aaef0bb341631952421cd90247439d2656cdd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 23 Jan 2023 18:35:32 +0100 Subject: [PATCH 0435/1232] ci_build.sh: try workarounds for old and broken install-sh [#1831] --- ci_build.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index ed18540330..29e4c10a3d 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1760,6 +1760,18 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # fail due to them: check_gitignore "all" || exit + if test -s "${SCRIPTDIR}/install-sh" \ + && ( grep -w MKDIRPROG "${SCRIPTDIR}/install-sh" \ + && { grep -v '#' "${SCRIPTDIR}/install-sh" | grep -E '\$mkdirprog.*-p' ; } ; \ + ) >/dev/null \ + ; then + if [ -z "${MKDIRPROG-}" ] ; then + echo "`date`: WARNING: setting MKDIRPROG to work around possible deficiencies of install-sh" + MKDIRPROG="mkdir -p" + export MKDIRPROG + fi + fi + [ -z "$CI_TIME" ] || echo "`date`: Trying to install the currently tested project into the custom DESTDIR..." $CI_TIME $MAKE $MAKE_FLAGS_VERBOSE DESTDIR="$INST_PREFIX" install [ -n "$CI_TIME" ] && echo "`date`: listing files installed into the custom DESTDIR..." && \ From 71b245b80b17005c8217d7396e8bb05f1e6fa5c3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 23 Jan 2023 21:06:54 +0000 Subject: [PATCH 0436/1232] configure.ac: fix condition and shorten the printed lines for install-sh warning --- configure.ac | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c0658fd7f1..0f3e54a254 100644 --- a/configure.ac +++ b/configure.ac @@ -4133,8 +4133,15 @@ NUT_PRINT_FEATURE_REPORT dnl Stopping short of patching the unknown script, we can warn about the issue dnl (visibly as it impacts next activities of the caller): -AS_IF([test -s "${ABS_TOP_SRCDIR}/install-sh" && (grep -w MKDIRPROG "${ABS_TOP_SRCDIR}/install-sh" && { grep -v '#' "${ABS_TOP_SRCDIR}/install-sh" | grep -E '\$mkdirprog.*-p' ; } ; ) >/dev/null], - [AC_MSG_WARN([Your system provided (or NUT tarball included) an 'install-sh' implementation]) - AC_MSG_WARN([which is not safe for parallel installs; export MKDIRPROG='mkdir -p' may help,]) - AC_MSG_WARN([otherwise run 'make install' sequentially. It should not impact parallel builds.]) +AS_IF([test -s "${ABS_TOP_SRCDIR}/install-sh" && grep -w MKDIRPROG "${ABS_TOP_SRCDIR}/install-sh" >/dev/null], + [AS_IF([grep -v '#' "${ABS_TOP_SRCDIR}/install-sh" | grep -E '\$mkdirprog.*-p' >/dev/null], + [], + [AC_MSG_WARN([=====================================================]) + AC_MSG_WARN([Your system provided (or NUT tarball included) an]) + AC_MSG_WARN(['install-sh' implementation which is not safe for]) + AC_MSG_WARN([parallel installs; export MKDIRPROG='mkdir -p']) + AC_MSG_WARN([may help, otherwise run 'make install' sequentially.]) + AC_MSG_WARN([This should not impact parallel builds.]) + AC_MSG_WARN([=====================================================]) ]) +]) From 0c6a039921cff7ed709eb4afb298ddc50676cc02 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 23 Jan 2023 21:13:50 +0000 Subject: [PATCH 0437/1232] ci_build.sh: fix condition and shorten the printed lines for install-sh warning --- ci_build.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 29e4c10a3d..42efd02298 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1761,14 +1761,17 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp check_gitignore "all" || exit if test -s "${SCRIPTDIR}/install-sh" \ - && ( grep -w MKDIRPROG "${SCRIPTDIR}/install-sh" \ - && { grep -v '#' "${SCRIPTDIR}/install-sh" | grep -E '\$mkdirprog.*-p' ; } ; \ - ) >/dev/null \ + && grep -w MKDIRPROG "${SCRIPTDIR}/install-sh" >/dev/null \ ; then - if [ -z "${MKDIRPROG-}" ] ; then - echo "`date`: WARNING: setting MKDIRPROG to work around possible deficiencies of install-sh" - MKDIRPROG="mkdir -p" - export MKDIRPROG + if grep -v '#' "${SCRIPTDIR}/install-sh" | grep -E '\$mkdirprog.*-p' >/dev/null \ + ; then + true + else + if [ -z "${MKDIRPROG-}" ] ; then + echo "`date`: WARNING: setting MKDIRPROG to work around possible deficiencies of install-sh" + MKDIRPROG="mkdir -p" + export MKDIRPROG + fi fi fi From 0c05a5d93a742c646aeb6cfa17f64a465e7fc4c8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 23 Jan 2023 22:55:21 +0000 Subject: [PATCH 0438/1232] ci_build.sh: suggest CI_REQUIRE_GOOD_GITIGNORE="false" in error message --- ci_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_build.sh b/ci_build.sh index 42efd02298..5351518cdc 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -615,7 +615,7 @@ check_gitignore() { if [ -n "`git status $GIT_ARGS -s "${FILE_GLOB}" | grep -E -v '^.. \.ci.*\.log.*' | grep -E "^.. ${FILE_REGEX}"`" ] \ && [ "$CI_REQUIRE_GOOD_GITIGNORE" != false ] \ ; then - echo "FATAL: There are changes in $FILE_DESCR files listed above - tracked sources should be updated in the PR (even if generated - not all builders can do so), and build products should be added to a .gitignore file, everything made should be cleaned and no tracked files should be removed!" >&2 + echo "FATAL: There are changes in $FILE_DESCR files listed above - tracked sources should be updated in the PR (even if generated - not all builders can do so), and build products should be added to a .gitignore file, everything made should be cleaned and no tracked files should be removed! You can 'export CI_REQUIRE_GOOD_GITIGNORE=false' if appropriate." >&2 if [ "$GIT_DIFF_SHOW" = true ]; then PAGER=cat git diff -- "${FILE_GLOB}" || true fi From 52187493ac6fdbc1441275457589ae04aa35f737 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 11:06:05 +0100 Subject: [PATCH 0439/1232] ci_build.sh: separate [build] and [check] failures (and successes) in BUILD_TYPE=default-all-errors reports --- ci_build.sh | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 5351518cdc..24ccacf166 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -524,6 +524,7 @@ configure_nut() { build_to_only_catch_errors_target() { if [ $# = 0 ]; then + # Re-enter with an arg list build_to_only_catch_errors_target all ; return $? fi @@ -546,9 +547,8 @@ build_to_only_catch_errors_target() { return 0 } -build_to_only_catch_errors() { - build_to_only_catch_errors_target all || return $? - +build_to_only_catch_errors_check() { + # Specifically run (an optional) "make check" if [ "${CI_SKIP_CHECK}" = true ] ; then echo "`date`: SKIP: not starting a '$MAKE check' for quick sanity test of the products built with the current compiler and standards, because caller requested CI_SKIP_CHECK=true; plain build has just succeeded however" return 0 @@ -562,6 +562,12 @@ build_to_only_catch_errors() { return 0 } +build_to_only_catch_errors() { + build_to_only_catch_errors_target all || return $? + build_to_only_catch_errors_check || return $? + return 0 +} + ccache_stats() { local WHEN="$1" [ -n "$WHEN" ] || WHEN="some time around the" @@ -1519,7 +1525,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp echo "=== Configured 'NUT_SSL_VARIANT=$NUT_SSL_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." cd "${CI_BUILDDIR}" - build_to_only_catch_errors && { + # Use default target e.g. "all": + build_to_only_catch_errors_target && { SUCCEEDED="${SUCCEEDED} NUT_SSL_VARIANT=${NUT_SSL_VARIANT}[build]" } || { RES_ALLERRORS=$? @@ -1532,6 +1539,19 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp fi } + build_to_only_catch_errors_check && { + SUCCEEDED="${SUCCEEDED} NUT_SSL_VARIANT=${NUT_SSL_VARIANT}[check]" + } || { + RES_ALLERRORS=$? + FAILED="${FAILED} NUT_SSL_VARIANT=${NUT_SSL_VARIANT}[check]" + # Help find end of build (before cleanup noise) in logs: + echo "=== FAILED 'NUT_SSL_VARIANT=${NUT_SSL_VARIANT}' check" + if [ "$CI_FAILFAST" = true ]; then + echo "===== Aborting because CI_FAILFAST=$CI_FAILFAST" >&2 + break + fi + } + # Note: when `expr` calculates a zero value below, it returns # an "erroneous" `1` as exit code. Why oh why?.. # (UPDATE: because expr returns boolean, and calculated 0 is false; @@ -1655,7 +1675,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp echo "=== Configured 'NUT_USB_VARIANT=$NUT_USB_VARIANT', $BUILDSTODO build variants (including this one) remaining to complete; trying to build..." cd "${CI_BUILDDIR}" - build_to_only_catch_errors && { + # Use default target e.g. "all": + build_to_only_catch_errors_target && { SUCCEEDED="${SUCCEEDED} NUT_USB_VARIANT=${NUT_USB_VARIANT}[build]" } || { RES_ALLERRORS=$? @@ -1668,6 +1689,19 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp fi } + build_to_only_catch_errors_check && { + SUCCEEDED="${SUCCEEDED} NUT_USB_VARIANT=${NUT_USB_VARIANT}[check]" + } || { + RES_ALLERRORS=$? + FAILED="${FAILED} NUT_USB_VARIANT=${NUT_USB_VARIANT}[check]" + # Help find end of build (before cleanup noise) in logs: + echo "=== FAILED 'NUT_USB_VARIANT=${NUT_USB_VARIANT}' check" + if [ "$CI_FAILFAST" = true ]; then + echo "===== Aborting because CI_FAILFAST=$CI_FAILFAST" >&2 + break + fi + } + # Note: when `expr` calculates a zero value below, it returns # an "erroneous" `1` as exit code. Notes above. BUILDSTODO="`expr $BUILDSTODO - 1`" || [ "$BUILDSTODO" = "0" ] || break From 572f62f9eb63cabf0fcb055341cf5fbebbed8eba Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 11:09:34 +0100 Subject: [PATCH 0440/1232] tests/NIT/nit.sh: have a sense of time in the log_*() messages When tests fail on CI farm, this should help see timeouts due to farm under too much stress vs. "real" reasonable problems. --- tests/NIT/nit.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 61349f23fe..424c2cfba3 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -45,20 +45,20 @@ shouldDebug() { log_debug() { if shouldDebug ; then - echo "[DEBUG] $@" >&2 + echo "`TZ=UTC LANG=C date` [DEBUG] $@" >&2 fi } log_info() { - echo "[INFO] $@" >&2 + echo "`TZ=UTC LANG=C date` [INFO] $@" >&2 } log_warn() { - echo "[WARNING] $@" >&2 + echo "`TZ=UTC LANG=C date` [WARNING] $@" >&2 } log_error() { - echo "[ERROR] $@" >&2 + echo "`TZ=UTC LANG=C date` [ERROR] $@" >&2 } report_NUT_PORT() { From a2f3143ad66b7323191233f6c743d2167622f7a3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 14:37:24 +0100 Subject: [PATCH 0441/1232] appveyor.yml: set ccache config options --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 33f99ea2b6..a0d86ca866 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,7 +48,7 @@ install: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc 'PATH="/mingw64/bin:$PATH" ; export PATH ; pwd ; ccache -sv || echo "SKIP: Could not query ccache stats"' + C:\msys64\usr\bin\bash -lc 'PATH="/mingw64/bin:$PATH" ; export PATH ; pwd ; { ccache -sv && ccache -o sloppiness = file_macro && ccache -o compression = true ; } || echo "SKIP: Could not query ccache stats"' before_build: From 9f801ea0ccbd7e74798af921c4bcb15bf0c455ec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 14:37:50 +0100 Subject: [PATCH 0442/1232] appveyor.yml: in the end, query ccache compression stats if supported --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a0d86ca866..9c8f5d9322 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -107,7 +107,7 @@ after_test: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -sv || ccache -s || echo "SKIP: Could not query ccache stats"' + C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; { { ccache -sv || ccache -s ; } && { ccache -x 2>/dev/null || true ; } ; } || echo "SKIP: Could not query ccache stats"' artifacts: From a431bed8ad801e779c18c8cb0ed9f8406571accc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 14:38:14 +0100 Subject: [PATCH 0443/1232] appveyor.yml: stash another possible ccache location --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9c8f5d9322..c78eb2ff1d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -125,6 +125,8 @@ artifacts: cache: - C:\msys64\home\appveyor\.ccache - C:\msys64\home\appveyor\ccache # likely missing, no problem - but the name is reported in ccache status + - C:\Users\appveyor\AppData\Local\ccache # may be default in newer versions + - C:\Users\appveyor\AppData\Local\.ccache # may be missing, but for completeness like above - C:\msys64\var\cache\pacman\pkg - C:\msys64\home\appveyor\nut-win-deps From 3288a81850d38bc0465cf89a32111a09e190999d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 14:41:27 +0100 Subject: [PATCH 0444/1232] ci_build.sh: in the end, query ccache compression stats if supported --- ci_build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 5351518cdc..8fb5659ea3 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -569,6 +569,12 @@ ccache_stats() { if [ -d "$CCACHE_DIR" ]; then echo "CCache stats $WHEN build:" ccache -s || true + # Some ccache versions support compression stats + # This may take time on slower systems however + # (and/or with larger cache contents) => off by default + if [ x"${CI_CCACHE_STATS_COMPRESSION-}" = xtrue ]; then + ccache -x 2>/dev/null || true + fi else echo "WARNING: CCache stats $WHEN build: tool is enabled, but CCACHE_DIR='$CCACHE_DIR' was not found now" >&2 fi From 7bd19461f6ab235010bd2d1972f97e83d1a7b83d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 16:10:25 +0100 Subject: [PATCH 0445/1232] appveyor.yml: avoid amperesand in YAML --- appveyor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c78eb2ff1d..6842311497 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,7 +48,7 @@ install: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc 'PATH="/mingw64/bin:$PATH" ; export PATH ; pwd ; { ccache -sv && ccache -o sloppiness = file_macro && ccache -o compression = true ; } || echo "SKIP: Could not query ccache stats"' + C:\msys64\usr\bin\bash -lc 'PATH="/mingw64/bin:$PATH" ; export PATH ; pwd ; ccache -sv || echo "SKIP: Could not query ccache stats" ; ccache -o sloppiness=file_macro || true ; ccache -o compression=true || true ' before_build: @@ -107,7 +107,8 @@ after_test: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 - C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; { { ccache -sv || ccache -s ; } && { ccache -x 2>/dev/null || true ; } ; } || echo "SKIP: Could not query ccache stats"' + C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -sv || ccache -s || echo "SKIP: Could not query ccache stats"' + C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -x 2>/dev/null || echo "SKIP: Could not query ccache compression stats"' artifacts: From 143c4d3a72bf86a6b39c615e0f6446398fced07e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 16:14:04 +0100 Subject: [PATCH 0446/1232] appveyor.yml: bolt ccache location to avoid wasting space on Appveyor for older vs newer layouts --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 6842311497..60b32e03b6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,7 @@ platform: x64 environment: APPVEYOR_SAVE_CACHE_ON_ERROR: true APPVEYOR_CACHE_ENTRY_ZIP_ARGS: -t7z -m0=lzma -mx=9 + CCACHE_DIR: /home/appveyor/.ccache # https://github.com/networkupstools/nut/blob/Windows-v2.8.0-1/docs/config-prereqs.txt#L951 # Note: not using `time` in scripts currently - they did upset From e9c287c81154d99d6e5366a6e15897bd493f00b0 Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Sun, 15 Jan 2023 08:47:03 -0500 Subject: [PATCH 0447/1232] drivers/bestfortress: Rationalize and improve debugging - Define a debug logging plan - Add debug log calls - Adjust several existing calls This commit does not intend to modify behavior other than logging. --- drivers/bestfortress.c | 131 +++++++++++++++++++++++++++++++++++------ 1 file changed, 113 insertions(+), 18 deletions(-) diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 45db52a769..fb369c313a 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -47,10 +47,29 @@ upsdrv_info_t upsdrv_info = { { NULL } }; +/* + * Logging plan: + * CRIT: executing poweroff + * ERR: indicates a bug in nut + * WARNING: indicates a serious misconfiguration that will cause nut + * to fail to function + * NOTICE: rare situations without a planned reporting path (none so + * far) + * INFO: One message each for startup, first establishment of comms + * DEBUG: Loss/restore of comms, and perhaps things that are normally + * reported via other daemons (on battery, low battery) + * D1: Things that happen rarely (startup/shutdown, param set, instant + * commands) + * D2: ? + * D3: trace of communications + * D4: more io than necessary to see working communications + * D5: log even succesful acks + */ + static int instcmd (const char *cmdname, const char *extra); static int upsdrv_setvar (const char *varname, const char *val); -/* rated VA load if known */ +/* Rated maximum VA output as configured by the user. */ static int maxload = 0; void upsdrv_initinfo(void) @@ -64,6 +83,8 @@ void upsdrv_initinfo(void) if (maxload) dstate_setinfo("ups.load", "0"); dstate_setinfo("output.voltamps", "0"); + + upsdebugx(1, "bestfortress: arbitrarily setting ups.delay.shutdown to 10"); dstate_setinfo("ups.delay.shutdown", "10"); /* write only */ /* tunable via front panel: (european voltage level) @@ -197,8 +218,12 @@ static int upssend(const char *fmt,...) { #endif va_end(ap); + /* Why do we not upsflushin here? */ + + upsdebugx(3, "upssend: sending %d bytes <%s>", ret, buf); + if ((ret < 1) || (ret >= (int) sizeof(buf))) - upslogx(LOG_WARNING, "ser_send_pace: vsnprintf needed more " + upslogx(LOG_ERR, "upssend: vsnprintf needed more " "than %d bytes", (int)sizeof(buf)); for (p = buf; *p && sent < INT_MAX - 1; p++) { @@ -224,22 +249,34 @@ static int upssend(const char *fmt,...) { sent++; if (sent >= INT_MAX) { - upslogx(LOG_WARNING, "ser_send_pace: sent more than INT_MAX, aborting"); + upslogx(LOG_ERR, "upssend: sent more than INT_MAX, aborting"); } } + if (ret != (int) sent) { + upsdebugx(1, "upssend: ret %d != sent %u", ret, sent); + } + return (int)sent; } static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic) { - return ser_get_line(upsfd, buf, bufsize - 1, ec, ic, - SER_WAIT_SEC, SER_WAIT_USEC); + ssize_t nread; + + nread = ser_get_line(upsfd, buf, bufsize - 1, ec, ic, + SER_WAIT_SEC, SER_WAIT_USEC); + + /* \todo is buf null terminated? */ + upsdebugx(4, "upsrecv read %d <%s>", (int) nread, buf); + + return nread; } static ssize_t upsflushin(int f, int verbose, const char *ignset) { NUT_UNUSED_VARIABLE(f); + upsdebugx(4, "upsflushin: begin"); return ser_flush_in(upsfd, ignset, verbose); } @@ -255,7 +292,7 @@ void upsdrv_updateinfo(void) char ch; int checksum_ok = -1, is_online = 1, is_off, low_batt, trimming, boosting; - upsdebugx(1, "upsdrv_updateinfo"); + upsdebugx(2, "upsdrv_updateinfo: begin"); for (retry = 0; retry < 5; ++retry) { upsflushin (0, 0, "\r "); @@ -264,14 +301,15 @@ void upsdrv_updateinfo(void) temp[2] = 0; do { if ((recv = upsrecv (temp+2, sizeof temp - 2, ENDCHAR, IGNCHARS)) <= 0) { + upsdebugx(1, "upsdrv_updateinfo: " + "upsrecv failed, retrying without counting"); upsflushin (0, 0, "\r "); upssend ("f\r"); while (ser_get_char(upsfd, &ch, 0, UPSDELAY) > 0 && ch != '\n'); /* response starts with \r\n */ } } while (temp[2] == 0); - upsdebugx(1, "upsdrv_updateinfo: received %" PRIiSIZE " bytes (try %i)", recv, retry); - upsdebug_hex(5, "buffer", temp, (size_t)recv); + upsdebugx(3, "upsdrv_updateinfo: received %" PRIiSIZE " bytes (try %i)", recv, retry); /* syslog (LOG_DAEMON | LOG_NOTICE,"ups: got %d chars '%s'\n", recv, temp + 2); */ /* status example: @@ -289,6 +327,16 @@ void upsdrv_updateinfo(void) checksum_ok = ( (checksum (temp+2) & 0xff) == 0 ); /* setinfo (INFO_, ""); */ + if (!checksum_ok) { + upsdebug_hex(5, "upsdrv_updateinfo: " + "checksum failure buffer hex", + temp, (size_t)recv); + upsdebug_ascii(5, "upsdrv_updateinfo: " + "checksum failure buffer ascii", + temp, (size_t)recv); + } + + /* 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. */ @@ -301,6 +349,8 @@ void upsdrv_updateinfo(void) else if (len != 80) checksum_ok = 0; if (checksum_ok) break; + + upsdebugx(1, "upsdrv_updateinfo: failed to read status try %d", retry); sleep(SER_WAIT_SEC); } @@ -317,7 +367,7 @@ void upsdrv_updateinfo(void) return; } - /* upslogx(LOG_INFO, "updateinfo: %s", p); */ + upsdebugx(3, "upsdrv_updateinfo: %s", p); setinfo_int ("input.voltage", p+24,4); setinfo_int ("output.voltage", p+28,4); @@ -368,11 +418,23 @@ void upsdrv_updateinfo(void) static int setparam (int parameter, int dlen, const char * data) { char reply[80]; + + upsdebugx(2, "setparam: begin"); + /* Note the use of "%*s" - parameter (int)dlen specifies * the string width reserved for data */ upssend ("p%d=%*s\r", parameter, dlen, data); - if (upsrecv (reply, sizeof(reply), ENDCHAR, "") < 0) return 0; - return strncmp (reply, "OK", 2) == 0; + if (upsrecv (reply, sizeof(reply), ENDCHAR, "") < 0) { + upsdebugx(1, "setparam: did not get reply"); + return 0; + } + if (strncmp (reply, "OK", 2) == 0) { + upsdebugx(5, "setparam: reply OK"); + return 1; + } else { + upsdebugx(1, "setparam: reply NOT ok"); + return 0; + } } /* ups_setsuper: set super-user access @@ -397,7 +459,7 @@ static void autorestart (int restart) static int upsdrv_setvar (const char *var, const char * data) { int parameter; size_t len = strlen(data); - upsdebugx(1, "Setvar: %s %s", var, data); + upsdebugx(1, "upsdrv_setvar: %s %s (%d bytes)", var, data, (int) len); if (strcmp("input.transfer.low", var) == 0) { parameter = 7; } @@ -408,7 +470,13 @@ static int upsdrv_setvar (const char *var, const char * data) { parameter = 2; } else { - upslogx(LOG_INFO, "Setvar: unsettable variable %s", var); + /* + * \todo Figure out if we get here by a code error or + * by the user asking for a variable that does not + * exist. If the former, change to LOG_ERR and if the + * latter change to LOG_DEBUG. + */ + upslogx(LOG_INFO, "upsdrv_setvar: unsettable variable %s", var); return STAT_SET_UNKNOWN; } ups_setsuper (1); @@ -420,18 +488,28 @@ static int upsdrv_setvar (const char *var, const char * data) { return STAT_SET_HANDLED; } +/* + * This is equivalent to the "shutdown.return" instant command. + * \todo Reduce duplication. + */ void upsdrv_shutdown(void) { const char *grace; + upsdebugx(2, "upsdrv_shutdown: invoked"); + grace = dstate_getinfo("ups.delay.shutdown"); - if (!grace) + if (!grace) { + upsdebugx(1, "upsdrv_shutdown: ups.delay.shutdown is NULL!"); grace = "1"; /* apparently, OFF0 does not work */ + } + + upslogx(LOG_CRIT, "upsdrv_shutdown: OFF/restart in %s seconds", grace); - printf ("shutdown in %s seconds\n", grace); /* make power return when utility power returns */ autorestart (1); + upssend ("OFF%s\r", grace); /* I'm nearly dead, Jim */ /* OFF will powercycle when line power is available again */ @@ -442,7 +520,7 @@ static int instcmd (const char *cmdname, const char *extra) const char *p; if (!strcasecmp(cmdname, "load.off")) { - printf ("powering off\n"); + upslogx(LOG_CRIT, "instcmd: %s: OFF/stayoff in 1s", cmdname); autorestart (0); upssend ("OFF1\r"); return STAT_INSTCMD_HANDLED; @@ -450,12 +528,13 @@ static int instcmd (const char *cmdname, const char *extra) else if (!strcasecmp(cmdname, "shutdown.return")) { p = dstate_getinfo ("ups.delay.shutdown"); if (!p) p = "1"; - printf ("shutdown in %s seconds\n", p); + upslogx(LOG_CRIT, "instcmd: %s: OFF/restart in %s seconds", cmdname, p); autorestart (1); upssend ("OFF%s\r", p); return STAT_INSTCMD_HANDLED; } - upslogx(LOG_INFO, "instcmd: unknown command [%s] [%s]", cmdname, extra); + /* \todo Software error or user error? */ + upslogx(LOG_ERR, "instcmd: unknown command [%s] [%s]", cmdname, extra); return STAT_INSTCMD_UNKNOWN; } @@ -488,6 +567,8 @@ void upsdrv_initups(void) char * speed_val = getval("baudrate"); char * max_load = getval("max_load"); + upsdebugx(1, "upsdrv_initups: begin"); + if (max_load) maxload = atoi(max_load); if (speed_val) { @@ -500,14 +581,28 @@ void upsdrv_initups(void) } upsfd = ser_open(device_path); + if (upsfd < 0) { + upslogx(LOG_WARNING, "failed to open %s", device_path); + /* \todo: Deal with the failure */ + } + + /* ser_set_speed returns int 0 always; fatal if ioctl fails */ ser_set_speed(upsfd, device_path, speed); + + upsdebugx(1, "upsdrv_initups: opened %s speed %s upsfd %d", + device_path, speed_val ? speed_val : "DEFAULT", upsfd); + + /* TODO: probe ups type */ /* the upsh handlers can't be done here, as they get initialized * shortly after upsdrv_initups returns to main. */ + + upsdebugx(1, "upsdrv_initups: end"); } void upsdrv_cleanup(void) { + upsdebugx(1, "upsdrv_cleanup: begin/end"); } From 019f66dff5db8b47723d7bb040fb7466865f4d4a Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Sun, 15 Jan 2023 20:03:35 -0500 Subject: [PATCH 0448/1232] driver/bestfortress: Fix serious shutdown bug and improve shutdown code - Move setting "ups.shutdown.delay" earlier so that it is available for `upsdrvctl shutdown`. This results in using that delay, instead of 1s. - Change shutdown delay to 20s from 10s, because that seems more common, and 10s feels too tight. - Add logging about shutdown. When run with `-k`, `ups.delay.shutdown` has apparently not been initialized. Fall back to 20, rather than 1, and log better. --- drivers/bestfortress.c | 55 ++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index fb369c313a..334b6915ae 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -35,7 +35,7 @@ #endif #define DRIVER_NAME "Best Fortress UPS driver" -#define DRIVER_VERSION "0.06" +#define DRIVER_VERSION "0.07" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -47,6 +47,11 @@ upsdrv_info_t upsdrv_info = { { NULL } }; +/* + * Choose 20s for off delay, reading the tea leaves from other drivers. + */ +static const char *shutdown_delay = "20"; + /* * Logging plan: * CRIT: executing poweroff @@ -72,6 +77,9 @@ static int upsdrv_setvar (const char *varname, const char *val); /* Rated maximum VA output as configured by the user. */ static int maxload = 0; +/* + * NB: Not called for shutdown. + */ void upsdrv_initinfo(void) { dstate_setinfo("ups.mfr", "Best Power"); @@ -84,9 +92,6 @@ void upsdrv_initinfo(void) dstate_setinfo("ups.load", "0"); dstate_setinfo("output.voltamps", "0"); - upsdebugx(1, "bestfortress: arbitrarily setting ups.delay.shutdown to 10"); - dstate_setinfo("ups.delay.shutdown", "10"); /* write only */ - /* tunable via front panel: (european voltage level) parameter factory default range INFO_LOWXFER 196 V p7=nnn 160-210 @@ -489,36 +494,44 @@ static int upsdrv_setvar (const char *var, const char * data) { } /* - * This is equivalent to the "shutdown.return" instant command. + * The "power down and maybe return command" is "OFF %d\r", with a + * delay in seconds before poweroff. As a special case, "OFF 0" does + * not shut down. The UPS will power on the load when power returns + * (or after a delay if power is not out), according to the front panel + * parameter, or the value set via `autorestart()`. + */ + +/* + * This is equivalent to the `shutdown.return` instant command, but + * invoked with `-k`. * \todo Reduce duplication. */ void upsdrv_shutdown(void) { const char *grace; - upsdebugx(2, "upsdrv_shutdown: invoked"); + upsdebugx(2, "upsdrv_shutdown: begin"); grace = dstate_getinfo("ups.delay.shutdown"); - if (!grace) { upsdebugx(1, "upsdrv_shutdown: ups.delay.shutdown is NULL!"); - grace = "1"; /* apparently, OFF0 does not work */ + /* Pick a different value than 20 so we can see it in the logs. */ + grace = "30"; } upslogx(LOG_CRIT, "upsdrv_shutdown: OFF/restart in %s seconds", grace); - /* make power return when utility power returns */ + /* Start again, overriding front panel setting. */ autorestart (1); upssend ("OFF%s\r", grace); /* I'm nearly dead, Jim */ - /* OFF will powercycle when line power is available again */ + + upsdebugx(2, "upsdrv_shutdown: end"); } static int instcmd (const char *cmdname, const char *extra) { - const char *p; - if (!strcasecmp(cmdname, "load.off")) { upslogx(LOG_CRIT, "instcmd: %s: OFF/stayoff in 1s", cmdname); autorestart (0); @@ -526,11 +539,8 @@ static int instcmd (const char *cmdname, const char *extra) return STAT_INSTCMD_HANDLED; } else if (!strcasecmp(cmdname, "shutdown.return")) { - p = dstate_getinfo ("ups.delay.shutdown"); - if (!p) p = "1"; - upslogx(LOG_CRIT, "instcmd: %s: OFF/restart in %s seconds", cmdname, p); - autorestart (1); - upssend ("OFF%s\r", p); + upsdebugx(2, "instcmd: %s: start", cmdname); + upsdrv_shutdown(); return STAT_INSTCMD_HANDLED; } /* \todo Software error or user error? */ @@ -560,6 +570,9 @@ static struct { {NULL, B1200}, }; +/* + * Called first, for normal operation and for shutdown. + */ void upsdrv_initups(void) { speed_t speed = B1200; @@ -592,12 +605,8 @@ void upsdrv_initups(void) upsdebugx(1, "upsdrv_initups: opened %s speed %s upsfd %d", device_path, speed_val ? speed_val : "DEFAULT", upsfd); - - /* TODO: probe ups type */ - - /* the upsh handlers can't be done here, as they get initialized - * shortly after upsdrv_initups returns to main. - */ + /* Set early so that it is in place for shutdown. */ + dstate_setinfo("ups.delay.shutdown", "%s", shutdown_delay); upsdebugx(1, "upsdrv_initups: end"); } From 1cb5a09c5753ab028eeef2710195e0b987d2f5a9 Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Fri, 20 Jan 2023 20:14:24 -0500 Subject: [PATCH 0449/1232] bestfortress: Switch logging to __func__ Add a few comments about needed future work, but no code changes. Adjust to (surprising to me) non-POSIX file descriptor types. --- drivers/bestfortress.c | 79 +++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 334b6915ae..aa85e45c10 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -225,11 +225,11 @@ static int upssend(const char *fmt,...) { /* Why do we not upsflushin here? */ - upsdebugx(3, "upssend: sending %d bytes <%s>", ret, buf); + upsdebugx(3, "%s: sending %d bytes <%s>", __func__, ret, buf); if ((ret < 1) || (ret >= (int) sizeof(buf))) - upslogx(LOG_ERR, "upssend: vsnprintf needed more " - "than %d bytes", (int)sizeof(buf)); + upslogx(LOG_ERR, "%s: vsnprintf needed more than %d bytes", + __func__, (int) sizeof(buf)); for (p = buf; *p && sent < INT_MAX - 1; p++) { #ifndef WIN32 @@ -254,12 +254,13 @@ static int upssend(const char *fmt,...) { sent++; if (sent >= INT_MAX) { - upslogx(LOG_ERR, "upssend: sent more than INT_MAX, aborting"); + upslogx(LOG_ERR, "%s: sent >= INT_MAX, aborting", + __func__); } } if (ret != (int) sent) { - upsdebugx(1, "upssend: ret %d != sent %u", ret, sent); + upsdebugx(1, "%s: ret %d != sent %u", __func__, ret, sent); } return (int)sent; @@ -273,7 +274,7 @@ static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic) SER_WAIT_SEC, SER_WAIT_USEC); /* \todo is buf null terminated? */ - upsdebugx(4, "upsrecv read %d <%s>", (int) nread, buf); + upsdebugx(4, "%s: read %d <%s>", __func__, (int) nread, buf); return nread; } @@ -281,7 +282,7 @@ static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic) static ssize_t upsflushin(int f, int verbose, const char *ignset) { NUT_UNUSED_VARIABLE(f); - upsdebugx(4, "upsflushin: begin"); + upsdebugx(4, "%s: begin", __func__); return ser_flush_in(upsfd, ignset, verbose); } @@ -297,7 +298,7 @@ void upsdrv_updateinfo(void) char ch; int checksum_ok = -1, is_online = 1, is_off, low_batt, trimming, boosting; - upsdebugx(2, "upsdrv_updateinfo: begin"); + upsdebugx(2, "%s: begin", __func__); for (retry = 0; retry < 5; ++retry) { upsflushin (0, 0, "\r "); @@ -306,15 +307,16 @@ void upsdrv_updateinfo(void) temp[2] = 0; do { if ((recv = upsrecv (temp+2, sizeof temp - 2, ENDCHAR, IGNCHARS)) <= 0) { - upsdebugx(1, "upsdrv_updateinfo: " - "upsrecv failed, retrying without counting"); + upsdebugx(1, "%s: upsrecv failed, " + "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 */ } } while (temp[2] == 0); - upsdebugx(3, "upsdrv_updateinfo: received %" PRIiSIZE " bytes (try %i)", recv, retry); + upsdebugx(3, "%s: received %" PRIiSIZE " bytes (try %i)", + __func__, recv, retry); /* syslog (LOG_DAEMON | LOG_NOTICE,"ups: got %d chars '%s'\n", recv, temp + 2); */ /* status example: @@ -355,24 +357,28 @@ void upsdrv_updateinfo(void) checksum_ok = 0; if (checksum_ok) break; - upsdebugx(1, "upsdrv_updateinfo: failed to read status try %d", retry); + upsdebugx(1, "%s: failed to read status try %d", + __func__, retry); sleep(SER_WAIT_SEC); } if (!p || len < 1 || checksum_ok < 0) { - upsdebugx(2, "pointer to data not initialized after processing"); + /* \todo: Analyze/fix code and rewrite message. */ + upsdebugx(2, "%s: pointer to data not initialized after processing", + __func__); dstate_datastale(); return; } if (!checksum_ok) { - upsdebugx(2, "checksum corruption"); + upsdebugx(2, "%s: checksum corruption", __func__); upsdebug_hex(3, "buffer", temp, (size_t)len); dstate_datastale(); return; } - upsdebugx(3, "upsdrv_updateinfo: %s", p); + /* Log assuming ASCII which it 99% is. \todo Improve. */ + upsdebugx(3, "%s: %s", __func__, p); setinfo_int ("input.voltage", p+24,4); setinfo_int ("output.voltage", p+28,4); @@ -424,20 +430,20 @@ static int setparam (int parameter, int dlen, const char * data) { char reply[80]; - upsdebugx(2, "setparam: begin"); + upsdebugx(2, "%s: begin", __func__); /* Note the use of "%*s" - parameter (int)dlen specifies * the string width reserved for data */ upssend ("p%d=%*s\r", parameter, dlen, data); if (upsrecv (reply, sizeof(reply), ENDCHAR, "") < 0) { - upsdebugx(1, "setparam: did not get reply"); + upsdebugx(1, "%s: did not get reply", __func__); return 0; } if (strncmp (reply, "OK", 2) == 0) { - upsdebugx(5, "setparam: reply OK"); + upsdebugx(5, "%s: reply OK", __func__); return 1; } else { - upsdebugx(1, "setparam: reply NOT ok"); + upsdebugx(1, "%s: reply NOT ok", __func__); return 0; } } @@ -464,7 +470,7 @@ static void autorestart (int restart) static int upsdrv_setvar (const char *var, const char * data) { int parameter; size_t len = strlen(data); - upsdebugx(1, "upsdrv_setvar: %s %s (%d bytes)", var, data, (int) len); + upsdebugx(1, "%s: %s %s (%d bytes)", __func__, var, data, (int) len); if (strcmp("input.transfer.low", var) == 0) { parameter = 7; } @@ -481,7 +487,7 @@ static int upsdrv_setvar (const char *var, const char * data) { * exist. If the former, change to LOG_ERR and if the * latter change to LOG_DEBUG. */ - upslogx(LOG_INFO, "upsdrv_setvar: unsettable variable %s", var); + upslogx(LOG_INFO, "%s: unsettable variable %s", __func__, var); return STAT_SET_UNKNOWN; } ups_setsuper (1); @@ -510,16 +516,16 @@ void upsdrv_shutdown(void) { const char *grace; - upsdebugx(2, "upsdrv_shutdown: begin"); + upsdebugx(2, "%s: begin", __func__); grace = dstate_getinfo("ups.delay.shutdown"); if (!grace) { - upsdebugx(1, "upsdrv_shutdown: ups.delay.shutdown is NULL!"); + upsdebugx(1, "%s: ups.delay.shutdown is NULL!", __func__); /* Pick a different value than 20 so we can see it in the logs. */ grace = "30"; } - upslogx(LOG_CRIT, "upsdrv_shutdown: OFF/restart in %s seconds", grace); + upslogx(LOG_CRIT, "%s: OFF/restart in %s seconds", __func__, grace); /* Start again, overriding front panel setting. */ autorestart (1); @@ -527,24 +533,26 @@ void upsdrv_shutdown(void) upssend ("OFF%s\r", grace); /* I'm nearly dead, Jim */ - upsdebugx(2, "upsdrv_shutdown: end"); + upsdebugx(2, "%s: end", __func__); } static int instcmd (const char *cmdname, const char *extra) { if (!strcasecmp(cmdname, "load.off")) { - upslogx(LOG_CRIT, "instcmd: %s: OFF/stayoff in 1s", cmdname); + upslogx(LOG_CRIT, "%s: %s: OFF/stayoff in 1s", + __func__, cmdname); autorestart (0); upssend ("OFF1\r"); return STAT_INSTCMD_HANDLED; } else if (!strcasecmp(cmdname, "shutdown.return")) { - upsdebugx(2, "instcmd: %s: start", cmdname); + upsdebugx(2, "%s: %s: start", __func__, cmdname); upsdrv_shutdown(); return STAT_INSTCMD_HANDLED; } /* \todo Software error or user error? */ - upslogx(LOG_ERR, "instcmd: unknown command [%s] [%s]", cmdname, extra); + upslogx(LOG_ERR, "%s: unknown command [%s] [%s]", + __func__, cmdname, extra); return STAT_INSTCMD_UNKNOWN; } @@ -580,7 +588,7 @@ void upsdrv_initups(void) char * speed_val = getval("baudrate"); char * max_load = getval("max_load"); - upsdebugx(1, "upsdrv_initups: begin"); + upsdebugx(1, "%s: begin", __func__); if (max_load) maxload = atoi(max_load); @@ -594,24 +602,25 @@ void upsdrv_initups(void) } upsfd = ser_open(device_path); - if (upsfd < 0) { - upslogx(LOG_WARNING, "failed to open %s", device_path); + if (INVALID_FD(upsfd)) { + upslogx(LOG_WARNING, "%s: failed to open %s", + __func__, device_path); /* \todo: Deal with the failure */ } /* ser_set_speed returns int 0 always; fatal if ioctl fails */ ser_set_speed(upsfd, device_path, speed); - upsdebugx(1, "upsdrv_initups: opened %s speed %s upsfd %d", - device_path, speed_val ? speed_val : "DEFAULT", upsfd); + upsdebugx(1, "%s: opened %s speed %s upsfd %d", + __func__, device_path, speed_val ? speed_val : "DEFAULT", upsfd); /* Set early so that it is in place for shutdown. */ dstate_setinfo("ups.delay.shutdown", "%s", shutdown_delay); - upsdebugx(1, "upsdrv_initups: end"); + upsdebugx(1, "%s: end", __func__); } void upsdrv_cleanup(void) { - upsdebugx(1, "upsdrv_cleanup: begin/end"); + upsdebugx(1, "%s: begin/end", __func__); } From edebda2b6e8e660d4d74bbc64dc70851a60c3d99 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 22 Jan 2023 17:54:13 +0100 Subject: [PATCH 0450/1232] Update bestfortress.c Fix prints of `(s)size_t` variables --- drivers/bestfortress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index aa85e45c10..67fd681b12 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -274,7 +274,7 @@ static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic) SER_WAIT_SEC, SER_WAIT_USEC); /* \todo is buf null terminated? */ - upsdebugx(4, "%s: read %d <%s>", __func__, (int) nread, buf); + upsdebugx(4, "%s: read %" PRIiSIZE " <%s>", __func__, nread, buf); return nread; } @@ -470,7 +470,7 @@ static void autorestart (int restart) static int upsdrv_setvar (const char *var, const char * data) { int parameter; size_t len = strlen(data); - upsdebugx(1, "%s: %s %s (%d bytes)", __func__, var, data, (int) len); + upsdebugx(1, "%s: %s %s (%" PRIuSIZE " bytes)", __func__, var, data, len); if (strcmp("input.transfer.low", var) == 0) { parameter = 7; } From ee1aa59ece0feb1762f8967470931f0533523f10 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 24 Jan 2023 09:03:56 +0100 Subject: [PATCH 0451/1232] NEWS: bestfortress shutdown timeout fixed [#1820] --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index bf6edd6055..f5b85d8bbd 100644 --- a/NEWS +++ b/NEWS @@ -136,6 +136,9 @@ https://github.com/networkupstools/nut/milestone/8 was tied to non-existent OIDs, not well handled in some parts of the driver [#1716] + - The `bestfortress` driver shutdown handling was fixed to use a non-trivial + default timeout [#1820] + - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] From 5d9458e226638ff62c2addb12eb67792d4375e0d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 26 Jan 2023 16:41:26 +0100 Subject: [PATCH 0452/1232] appveyor.yml: avoid redirect to /dev/null on Windows --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 60b32e03b6..20b9bbe9ec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -109,7 +109,7 @@ after_test: REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -sv || ccache -s || echo "SKIP: Could not query ccache stats"' - C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -x 2>/dev/null || echo "SKIP: Could not query ccache compression stats"' + C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" ; export PATH ; ccache -x || echo "SKIP: Could not query ccache compression stats"' artifacts: From bc887560ce0de57a00cb698cc0bccdfb9f02174f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Feb 2023 11:07:30 +0100 Subject: [PATCH 0453/1232] configure.ac: quiesce python checks for modules --- configure.ac | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 0f3e54a254..c5bf92d576 100644 --- a/configure.ac +++ b/configure.ac @@ -1763,13 +1763,16 @@ nut_with_nut_monitor_py3qt5="" nut_with_nut_monitor_desktop="" dnl TODO: Add a way to define this path? will have app/ maybe module/ inside... nut_with_nut_monitor_dir="${datarootdir}/nut-monitor" +PYTHON_FAILED_TEST_DETAILS="" if test x"${nut_with_nut_monitor}" != xno ; then dnl While we might just install for "yes" request, in hopes user would dnl get their python ecosystem in place later, we need some criteria to dnl avoid installing it always :) Also, need to substitute the shebang. if test -z "${PYTHON}${PYTHON2}${PYTHON3}" ; then case "${nut_with_nut_monitor}" in - "auto") nut_with_nut_monitor="no" ;; + "auto") nut_with_nut_monitor="no" + PYTHON_FAILED_TEST_DETAILS="No python 2/3 interpreter was found" + ;; "yes") AC_MSG_ERROR([No python 2/3 interpreter was found, required for NUT-Monitor desktop application]) ;; esac @@ -1778,21 +1781,29 @@ fi if test x"${nut_with_nut_monitor}" != xno ; then dnl Note: no double-quoting for use, the command string may be multi-token + dnl HACK NOTE: Here we redirect outputs to "&5" which is autoconf stream + dnl for "config.log" details since... forever? Still, hardcoded numbers... + PYTHON2_TEST_MODULES="re,glob,codecs,gtk,gtk.glade,gobject,ConfigParser" + PYTHON3_TEST_MODULES="re,glob,codecs,PyQt5.uic,configparser" if test -n "${PYTHON2}" \ && (command -v ${PYTHON2} || which ${PYTHON2}) >/dev/null 2>/dev/null \ ; then - if ${PYTHON2} -c "import re,glob,codecs,gtk,gtk.glade,gobject,ConfigParser" \ + if ${PYTHON2} -c "import ${PYTHON2_TEST_MODULES}" 1>&5 2>&5 \ ; then nut_with_nut_monitor_py2gtk2="yes" + else + PYTHON_FAILED_TEST_DETAILS="Missing some or all of these Python2 modules: '${PYTHON2_TEST_MODULES}'" fi fi if test -n "${PYTHON3}" \ && (command -v ${PYTHON3} || which ${PYTHON3}) >/dev/null 2>/dev/null \ ; then - if ${PYTHON3} -c "import re,glob,codecs,PyQt5.uic,configparser" \ + if ${PYTHON3} -c "import ${PYTHON3_TEST_MODULES}" 1>&5 2>&5 \ ; then nut_with_nut_monitor_py3qt5="yes" + else + PYTHON_FAILED_TEST_DETAILS="Missing some or all of these Python3 modules: '${PYTHON3_TEST_MODULES}'" fi fi @@ -1801,14 +1812,23 @@ if test x"${nut_with_nut_monitor}" != xno ; then && test -n "${PYTHON}" \ && (command -v ${PYTHON} || which ${PYTHON2}) >/dev/null 2>/dev/null \ ; then - if ${PYTHON} -c "import re,glob,codecs,PyQt5.uic,configparser" \ + if ${PYTHON} -c "import ${PYTHON3_TEST_MODULES}" 1>&5 2>&5 \ ; then nut_with_nut_monitor_py3qt5="yes" + else + PYTHON_FAILED_TEST_DETAILS="Missing some or all of these Python3 modules: '${PYTHON3_TEST_MODULES}'" fi - if ${PYTHON} -c "import re,glob,codecs,gtk,gtk.glade,gobject,ConfigParser" \ + if ${PYTHON} -c "import ${PYTHON2_TEST_MODULES}" 1>&5 2>&5 \ ; then nut_with_nut_monitor_py2gtk2="yes" + PYTHON_FAILED_TEST_DETAILS="" + else + if test -n "${PYTHON_FAILED_TEST_DETAILS}" ; then + PYTHON_FAILED_TEST_DETAILS="${PYTHON_FAILED_TEST_DETAILS} and some or all of these Python2 modules: '${PYTHON2_TEST_MODULES}'" + else + PYTHON_FAILED_TEST_DETAILS="Missing some or all of these Python2 modules: '${PYTHON2_TEST_MODULES}'" + fi fi fi @@ -1821,12 +1841,20 @@ if test x"${nut_with_nut_monitor}" != xno ; then case "${nut_with_nut_monitor}" in "auto") nut_with_nut_monitor="no" ;; "yes") - AC_MSG_ERROR([No python 2/3 interpreter with needed modules was found, as required for NUT-Monitor desktop application]) + AC_MSG_ERROR([No python 2/3 interpreter with needed modules was found, as required for NUT-Monitor desktop application: ${PYTHON_FAILED_TEST_DETAILS}]) ;; esac fi fi -AC_MSG_RESULT([${nut_with_nut_monitor}]) +case "${nut_with_nut_monitor}" in + "no") if test -n "${PYTHON_FAILED_TEST_DETAILS}" ; then + AC_MSG_RESULT([${nut_with_nut_monitor}: ${PYTHON_FAILED_TEST_DETAILS}]) + else + AC_MSG_RESULT([${nut_with_nut_monitor}]) + fi + ;; + *) AC_MSG_RESULT([${nut_with_nut_monitor}]) ;; +esac if test x"${nut_with_nut_monitor}" != xno ; then if (command -v desktop-file-install || which desktop-file-install) >/dev/null 2>/dev/null ; then From 5dd07586d5c2c6b97bfdb610f6f8468ed16315f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Feb 2023 11:29:23 +0100 Subject: [PATCH 0454/1232] configure.ac: rearrange progress message for "whether to build binaries with tighter systemd integration support" --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c5bf92d576..9dc50f3a74 100644 --- a/configure.ac +++ b/configure.ac @@ -2928,10 +2928,10 @@ dnl of building and delivering unit files (which may be crafted separately). dnl TODO: although end-user deployments (for custom builds) may be lacking dnl libsystemd development files, they might have a `systemd-notify` program dnl intended to help scripted service units. Consider making use of that then. -AC_MSG_CHECKING(whether to build binaries with tighter systemd integration support) NUT_ARG_WITH([libsystemd], [build binaries with tighter systemd integration (notifications etc)], [auto]) NUT_CHECK_LIBSYSTEMD +AC_MSG_CHECKING(whether requested and can build binaries with tighter systemd integration support) AS_IF([test x"${nut_with_libsystemd}" = xyes && test x"${nut_have_libsystemd}" != xyes], [AC_MSG_ERROR([--with-libsystemd was requested, but the library was not found or usable])]) AS_CASE(["${nut_with_libsystemd}"], From 6e1ad7c40325e90f7f097ccc0c6126369941c068 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 2 Feb 2023 15:55:17 +0100 Subject: [PATCH 0455/1232] docs/nut.dict: add OSC and opencollective --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 7223daa387..7b70de9979 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3088 utf-8 +personal_ws-1.1 en 3090 utf-8 AAS ABI ACFAIL @@ -792,6 +792,7 @@ ONF ONV OOM OSABI +OSC OSF OSs OUTDIR @@ -2418,6 +2419,7 @@ ontimedays ontiniedays ooce openSUSE +opencollective openipmi openjdk openlog From 7a207235fd3e4d85fea51af489c079a4da195c9b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 3 Feb 2023 13:23:09 +0100 Subject: [PATCH 0456/1232] Introduce .github/FUNDING.yml metadata --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..a36f1ed44c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: networkupstools +open_collective: networkupstools From b5a57fe7150a709edd27ec2ddfaa7ce152eef08a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 5 Feb 2023 15:10:44 +0100 Subject: [PATCH 0457/1232] INSTALL.nut: update with "in-place" rebuilds chapter [#1826] --- INSTALL.nut | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/nut.dict | 7 +- 2 files changed, 251 insertions(+), 1 deletion(-) diff --git a/INSTALL.nut b/INSTALL.nut index 4b99ba6a14..faa15d8cb2 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -22,6 +22,9 @@ To build NUT from a Git checkout you may need some additional tools (referenced just a bit below) and run `./autogen.sh` to generate the needed files. For common developer iterations, porting to new platforms, or in-place testing, running the `./ci_build.sh` script can be helpful. +The "<>" section details some more hints about such workflow, including some +`systemd` integration. The NUT linkdoc:packager-guide[Packager Guide], which presents the best practices for installing and integrating NUT, is also a good reading. @@ -80,6 +83,9 @@ do this, you will have problems later on when you try to start upsd. Build and install ~~~~~~~~~~~~~~~~~ +NOTE: See also <>. + [[Configuration]] Configuration ^^^^^^^^^^^^^ @@ -210,6 +216,245 @@ You are now ready to configure NUT, and start testing and using it. You can jump directly to the <>. +[[Installing_inplace]] +Building NUT for in‐place upgrades or non‐disruptive tests +---------------------------------------------------------- + +NOTE: The NUT GitHub Wiki article at +https://github.com/networkupstools/nut/wiki/Building-NUT-for-in%E2%80%90place-upgrades-or-non%E2%80%90disruptive-tests +may contain some more hints as contributed by the community. + +Overview +~~~~~~~~ + +Since late 2022/early 2023 NUT codebase supports "in-place" builds +which try their best to discover the configuration of an earlier build +(configuration and run-time paths and OS accounts involved, maybe an +exact configuration if stored in deployed binaries). + +This optional mode is primarily intended for several use-cases: + +* Test recent GitHub "master" branch or a proposed PR to see if it + solves a practical problem for a particular user; +* Replace an existing deployment, e.g. if OS-provided packages deliver + obsolete code, to use newer NUT locally in "production mode". + - In such cases ideally get your distribution, NAS vendor, etc. + to provide current NUT -- and benefit from a better integrated + and tested product. + +Note that "just testing" often involves building the codebase and new +drivers or tools in question, and running them right from the build +workspace (without installing into the system and so risking an +unpredictable-stability state). In case of testing new driver builds, +note that you would need to stop the normally running instances to +free up the communications resources (USB/serial ports, etc.), run the +new driver program in data-dump mode, and restart the normal systems +operations. + +Such tests still benefit from matching the build configuration to what +is already deployed, in order to request same configuration files and +system access permissions (e.g. to own device nodes for physical-media +ports involved, and to read the production configuration files). + +Pre-requisites +^^^^^^^^^^^^^^ + +The <> +document details tools and dependencies that were added on NUT CI build +environments, which now cover many operating systems. This should +provide a decent starting point for the build on yours (PRs to update +the document are welcome!) + +NOTE: "Config Prereqs" document for latest NUT iteration can be found at +https://github.com/networkupstools/nut/blob/master/docs/config-prereqs.txt + +Note that unlike distribution tarballs, Git sources do not include a +`configure` script and some other files -- these should be generated by +running `autogen.sh` (or `ci_build.sh` that calls it). + +Getting the right sources +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To build the current tip of development iterations (usually after PR +merges that passed CI, reviews and/or other tests), just clone the NUT +repository and "master" branch should get checked out by default (also +can request that explicitly, per example posted below). + +If you want to quickly test a particular pull request, see the link on +top of the PR page that says `... wants to merge ... from : ...` and +copy the proposed-source URL of that "from" part. + +For example, in some PR this says `jimklimov:issue-1234` and links to +`https://github.com/jimklimov/nut/tree/issue-1234`. +For manual git-cloning, just paste that URL into the shell and replace +the `/tree/` with "`-b`" CLI option for branch selection, like this: + + :; cd /tmp + ### Checkout https://github.com/jimklimov/nut/tree/issue-1234 + :; git clone https://github.com/jimklimov/nut -b issue-1234 + +Testing with CI helper +~~~~~~~~~~~~~~~~~~~~~~ + +NOTE: this uses the `ci_build.sh` script to arrange some rituals and +settings, in this case primarily to default the choice of drivers to +auto-detection of what can be built, and to skip building documentation. +Also note that this script supports many other scenarios for CI and +developers, managed by `BUILD_TYPE` and other environment variables, +which are not explored here. + +An "in-place" _testing_ build and run would probably go along these lines: + + :; cd /tmp + :; git clone -b master https://github.com/networkupstools/nut + :; cd nut + :; ./ci_build.sh inplace + ### Temporarily stop your original drivers + :; ./drivers/nutdrv_qx -a DEVNAME_FROM_UPS_CONF -d1 -DDDDDD \ + # -x override...=... -x subdriver=... + ### Can start back your original drivers + ### Analyze and/or post back the data-dump + +[NOTE] +====== +To probe a device for which you do not have an `ups.conf` section +yet, you must specify `-s name` and all config options (including +`port`) on command-line with `-x` arguments, e.g.: + + :; ./drivers/nutdrv_qx -s temp-ups \ + -d1 -DDDDDD -x port=auto \ + -x vendorid=... -x productid=... \ + -x subdriver=... +====== + +Replacing a NUT deployment +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While `ci_build.sh inplace` can be a viable option for preparation of +local builds, you may want to have precise control over `configure` +options (e.g. choice of required drivers, or enabled documentation). + +A sound starting point would be to track down packaging recipes used by +your distribution (e.g. +link:https://src.fedoraproject.org/rpms/nut/blob/rawhide/f/nut.spec[RPM spec] +or +link:https://salsa.debian.org/debian/nut/-/blob/debian/debian/rules[DEB rules] +files, etc.) to detail the same paths if you intend to replace those, +and copy the parameters for `configure` script from there -- especially +if your system is not currently running NUT v2.8.1 or newer (which embeds +this information to facilitate in-place upgrade rebuilds). + +Note that the primary focus of in-place automated configuration mode is +about critical run-time options, such as OS user accounts, configuration +location and state/PID paths, so it alone might not replace your driver +binaries that the package would put into an obscure location like +`/lib/nut`. It would however install init-scripts or systemd units that +would refer to new locations specified by the current build, so such old +binaries would just consume disk space but not run. + +Replacing any NUT deployment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +NOTE: For deployments on OSes with `systemd` see the next section. + +This goes similar to usual build and install from Git: + + :; cd /tmp + :; git clone https://github.com/networkupstools/nut + :; cd nut + :; ./autogen.sh + :; ./configure --enable-inplace-runtime # --maybe-some-other-options + :; make -j 4 all check && sudo make install + +Note that `make install` does not currently handle all the nuances that +packaging installation scripts would, such as customizing filesystem +object ownership, daemon restarts, etc. or even creating locations like +`/var/state/ups` and `/var/run/nut` as part of the `make` target (but +e.g. the delivered `systemd-tmpfiles` configuration can handle that for +a large part of the audience). This aspect is tracked as +link:https://github.com/networkupstools/nut/issues/1298[issue #1298] + +At this point you should revise the locations for PID files +(e.g. `/var/run/nut`) and pipe files (e.g. `/var/state/ups`) that they +exist and permissions remain suitable for NUT run-time user selected by +your configuration, and typically stop your original NUT drivers, +data-server (upsd) and upsmon, and restart them using the new binaries. + +Replacing a systemd-enabled NUT deployment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For modern Linux distributions with `systemd` this replacement procedure +could be enhanced like below, to also re-enable services (creating proper +symlinks) and to get them started: + + :; cd /tmp + :; git clone https://github.com/networkupstools/nut + :; cd nut + :; ./autogen.sh + :; ./configure --enable-inplace-runtime # --maybe-some-other-options + :; make -j 4 all check && \ + { sudo systemctl stop nut-monitor nut-server || true ; } && \ + { sudo systemctl stop nut-driver.service || true ; } && \ + { sudo systemctl stop nut-driver.target || true ; } && \ + { sudo systemctl stop nut.target || true ; } && \ + sudo make install && \ + sudo systemctl daemon-reload && \ + sudo systemd-tmpfiles --create && \ + sudo systemctl disable nut.target nut-driver.target \ + nut-monitor nut-server nut-driver-enumerator.path \ + nut-driver-enumerator.service && \ + sudo systemctl enable nut.target nut-driver.target \ + nut-monitor nut-server nut-driver-enumerator.path \ + nut-driver-enumerator.service && \ + { sudo systemctl restart udev || true ; } && \ + sudo systemctl restart nut-driver-enumerator.service \ + nut-monitor nut-server + +Note the several attempts to stop old service units -- naming did change +from 2.7.4 and older releases, through 2.8.0, and up to current codebase. +Most of the NUT units are now `WantedBy=nut.target` (which is in turn +`WantedBy=multi-user.target` and so bound to system startup). You should +only `systemctl enable` those units you need on this system -- this allows +it to not start the daemons you do not need (e.g. not run `upsd` NUT data +server on systems which are only `upsmon secondary` clients). + +The `nut-driver-enumerator` units (and corresponding shell script) are +part of a new feature introduced in NUT 2.8.0, which automatically +discovers `ups.conf` sections and changes to their contents, and manages +instances of a `nut-driver@.service` definition. + +You may also have to restart (or reload if supported) some system services +if your updates impact them, like `udev` for updates USB support (note also +link:https://github.com/networkupstools/nut/pull/1342[PR #1342] regarding +the change from `udev.rules` to `udev.hwdb` file with NUT v2.8.0 or later -- +you may have to remove the older file manually). + +Iterating with a systemd deployment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are regularly building NUT from GitHub "master" branch, or iterating +local development branches of your own, you *may* get away with shorter +constructs to just restart the services after installing newly built files +(if you know there were no changes to unit file definitions and dependencies), +e.g.: + + ... + :; make -j 4 all check && \ + sudo make install && \ + sudo systemctl daemon-reload && \ + sudo systemd-tmpfiles --create && \ + sudo systemctl restart \ + nut-driver-enumerator.service nut-monitor nut-server + +Next steps after an in-place upgrade +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can jump directly to the <> +if you need to revise the settings for your new NUT version, take advantage +of new configuration options, etc. + +Check the linkdoc:NEWS and linkdoc:UPGRADING[Upgrade Notes] files in your +Git workspace to review features that should be present in your new build. [[Installing_packages]] Installing from packages diff --git a/docs/nut.dict b/docs/nut.dict index 7b70de9979..bbc8bdc5df 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3090 utf-8 +personal_ws-1.1 en 3095 utf-8 AAS ABI ACFAIL @@ -236,6 +236,7 @@ DATAPATH DCE DDD DDDDD +DDDDDD DDF DDThh DEADTIME @@ -247,6 +248,7 @@ DELPHYS DELRANGE DES DESTDIR +DEVNAME DF DHEA DIGYS @@ -1346,6 +1348,7 @@ WS WSE WTU Waldie +WantedBy WatchdogSec Werror Wextra @@ -1992,6 +1995,7 @@ httpd https huawei hunnox +hwdb hypervisor hypervisors iBox @@ -2082,6 +2086,7 @@ jbus jdk jenkins jessie +jimklimov journalctl jpg jpgraph From 908dd96e8160b3e5d9892e0a88d7f53c7df09aec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 7 Feb 2023 11:11:02 +0100 Subject: [PATCH 0458/1232] INSTALL.nut: fix link to Config Prereqs in generated HTML version --- INSTALL.nut | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/INSTALL.nut b/INSTALL.nut index faa15d8cb2..266f0b7153 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -29,13 +29,17 @@ tests>>" section details some more hints about such workflow, including some The NUT linkdoc:packager-guide[Packager Guide], which presents the best practices for installing and integrating NUT, is also a good reading. -The link:config-prereqs.txt[Prerequisites for building NUT on different OSes] +The <> document suggests prerequisite packages with tools and dependencies available and needed to build and test as much as possible of NUT on numerous platforms, written from perspective of CI testing (if you are interested in getting updated drivers for a particular device, you might select a sub-set of those suggestions). +NOTE: This "Config Prereqs" document for latest NUT iteration can be found at +https://github.com/networkupstools/nut/blob/master/docs/config-prereqs.txt +or as `docs/config-prereqs.txt` in your build workspace (from Git or tarball). + [NOTE] .Keep in mind that... ================================================================================ @@ -265,9 +269,6 @@ environments, which now cover many operating systems. This should provide a decent starting point for the build on yours (PRs to update the document are welcome!) -NOTE: "Config Prereqs" document for latest NUT iteration can be found at -https://github.com/networkupstools/nut/blob/master/docs/config-prereqs.txt - Note that unlike distribution tarballs, Git sources do not include a `configure` script and some other files -- these should be generated by running `autogen.sh` (or `ci_build.sh` that calls it). From 3dae58f403f88dace52e2caac3c0690e45b8ef22 Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Sat, 11 Feb 2023 21:18:59 +0000 Subject: [PATCH 0459/1232] huawei-ups2000: fix broken timeout recovery behavior in Issue #1846. Occasionally, the UPS takes longer than 1 second to respond and finish transmitting a message. This causes a timeout in modbus_read_registers(), and the driver is supposed to retry the request and recover from the failure. Unfortunately, when the driver retries, instead of getting the result of the current request, the leftover bytes from the previous read is received from the serial buffer, creating invalid messages. It causes all following reads to also fail, often with an "Invalid CRC" error, and the driver can never recovery from the failure. This commit fixes the bug by flushing the buffer using function modbus_flush() before invoking modbus_read_registers(). The libmodbus timeout value is also bumped to 2 seconds to avoid unnecessary timeouts and subsequent retries. Finally, the version number is also bumped to reflect the existence of this fix. Signed-off-by: Yifeng Li --- drivers/huawei-ups2000.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index 81d5924d40..8c811c4856 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -51,7 +51,7 @@ #include "timehead.h" /* fallback gmtime_r() variants if needed (e.g. some WIN32) */ #define DRIVER_NAME "NUT Huawei UPS2000 (1kVA-3kVA) RS-232 Modbus driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" #define CHECK_BIT(var,pos) ((var) & (1<<(pos))) #define MODBUS_SLAVE_ID 1 @@ -225,12 +225,15 @@ void upsdrv_initups(void) fatalx(EXIT_FAILURE, "Unable to create the libmodbus context"); #if LIBMODBUS_VERSION_CHECK(3, 1, 2) - /* It can take as slow as 1 sec. for the UPS to respond. */ - modbus_set_response_timeout(modbus_ctx, 1, 0); + /* + * Although it rarely occurs, it can take as slow as 2 sec. for the + * UPS to respond a read and finish transmitting the message. + */ + modbus_set_response_timeout(modbus_ctx, 2, 0); #else { struct timeval timeout; - timeout.tv_sec = 1; + timeout.tv_sec = 2; timeout.tv_usec = 0; modbus_set_response_timeout(modbus_ctx, &timeout); } @@ -1945,6 +1948,16 @@ static int ups2000_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *des "Please file a bug report!", addr); for (i = 0; i < 3; i++) { + /* + * If the previous read failed with a timeout, often there + * are still unprocessed bytes in the serial buffer and they + * would be mixed with the new data, creating invalid messages, + * making all subsequent reads to fail as well. + * + * Flush read buffer first to avoid it. + */ + modbus_flush(ctx); + r = modbus_read_registers(ctx, addr, nb, dest); /* generic retry for modbus read failures. */ From 8c6d7afada0c1be8e60f069a70c316f818be33ba Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Feb 2023 11:44:47 +0100 Subject: [PATCH 0460/1232] configure.ac: --enable-inplace-runtime should not disregard sysconfdir which the build user may not read --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index 9dc50f3a74..550ec77a1d 100644 --- a/configure.ac +++ b/configure.ac @@ -325,6 +325,13 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ ; then sysconfdir="$D" break + else + if test -d "$D/" && test ! -r "$D/" ; then + dnl Keeping order of preference defined by "for" loop: + AC_MSG_WARN([Picking directory '${D}' which exists but current build user may not read]) + sysconfdir="$D" + break + fi fi done AC_MSG_RESULT([${sysconfdir}]) From d965efcc76c4951f15a4e310034eaffc09addff2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Feb 2023 11:49:02 +0100 Subject: [PATCH 0461/1232] drivers/main.c: options '-a id' and '-s id' are mutually exclusive and single-use only --- drivers/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index eb254a9840..1bece4f076 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -749,6 +749,10 @@ int main(int argc, char **argv) while ((i = getopt(argc, argv, "+a:s:kFBDd:hx:Lqr:u:g:Vi:")) != -1) { switch (i) { case 'a': + if (upsname) + fatalx(EXIT_FAILURE, "Error: options '-a id' and '-s id' " + "are mutually exclusive and single-use only."); + upsname = optarg; read_upsconf(); @@ -758,6 +762,10 @@ int main(int argc, char **argv) optarg); break; case 's': + if (upsname) + fatalx(EXIT_FAILURE, "Error: options '-a id' and '-s id' " + "are mutually exclusive and single-use only."); + upsname = optarg; upsname_found = 1; break; From 81389d4e458fc2079c81c33d9d932607aa845efc Mon Sep 17 00:00:00 2001 From: Jon Gilmore Date: Sun, 12 Feb 2023 08:59:44 -0600 Subject: [PATCH 0462/1232] add support for minuteman device a0a0 --- drivers/tripplite-hid.c | 2 ++ scripts/upower/95-upower-hid.hwdb | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/tripplite-hid.c b/drivers/tripplite-hid.c index f661401362..ac6fe0129c 100644 --- a/drivers/tripplite-hid.c +++ b/drivers/tripplite-hid.c @@ -154,6 +154,8 @@ static usb_device_id_t tripplite_usb_device_table[] = { /* Delta/Minuteman Enterprise Plus E1500RM2U */ { USB_DEVICE(DELTA_VENDORID, 0xa011), battery_scale_1dot0 }, + /* Delta/Minuteman PRO1500RT2U */ + { USB_DEVICE(DELTA_VENDORID, 0xa0a0), battery_scale_1dot0 }, /* Terminating entry */ { 0, 0, NULL } diff --git a/scripts/upower/95-upower-hid.hwdb b/scripts/upower/95-upower-hid.hwdb index c5f0bdacdb..287c3f97fd 100644 --- a/scripts/upower/95-upower-hid.hwdb +++ b/scripts/upower/95-upower-hid.hwdb @@ -82,6 +82,7 @@ usb:v0592p0004* # Delta UPS usb:v05DDp041B* usb:v05DDpA011* +usb:v05DDpA0A0* UPOWER_BATTERY_TYPE=ups UPOWER_VENDOR=Delta UPS From 0e90cc97645cbef337614b4e35b4d3f271b6d5c9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 12 Feb 2023 17:42:35 +0100 Subject: [PATCH 0463/1232] Update tripplite-hid.c Update subdriver version along with content bump --- drivers/tripplite-hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tripplite-hid.c b/drivers/tripplite-hid.c index ac6fe0129c..ed93b3dd4d 100644 --- a/drivers/tripplite-hid.c +++ b/drivers/tripplite-hid.c @@ -29,7 +29,7 @@ #include "tripplite-hid.h" #include "usb-common.h" -#define TRIPPLITE_HID_VERSION "TrippLite HID 0.84" +#define TRIPPLITE_HID_VERSION "TrippLite HID 0.85" /* FIXME: experimental flag to be put in upsdrv_info */ From bb4f72a6804a4e1e6aebef21ac0af81a2d22bddd Mon Sep 17 00:00:00 2001 From: modrisb Date: Mon, 20 Feb 2023 21:44:17 +0200 Subject: [PATCH 0464/1232] initial for gpio driver support --- configure.ac | 24 +- drivers/Makefile.am | 12 +- drivers/gpio.c | 645 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 679 insertions(+), 2 deletions(-) create mode 100644 drivers/gpio.c diff --git a/configure.ac b/configure.ac index 550ec77a1d..25ca70187f 100644 --- a/configure.ac +++ b/configure.ac @@ -977,6 +977,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_gpio}"; then with_gpio="yes"; fi dnl Platform-dependent snowflakes that are required or auto: if test -z "${with_linux_i2c}"; then @@ -1004,6 +1005,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_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 AC_MSG_RESULT(${DRIVER_BUILD_LIST}) @@ -1019,7 +1021,7 @@ 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" + POWERMAN_DRIVERLIST IPMI_DRIVERLIST GPIO_DRIVERLIST" get_drvlist() ( dnl Note escaped brackets - "against" m4 parser @@ -1131,6 +1133,11 @@ AC_ARG_WITH(drivers, [AC_MSG_NOTICE([Requiring --with-ipmi=yes for driver "$DRV"]) with_ipmi=yes] )], + [GPIO_DRIVERLIST], [ + AS_IF([test -z "${with_gpio}"], + [AC_MSG_NOTICE([Requiring --with-gpio=yes for driver "$DRV"]) + with_gpio=yes] + )], [AC_MSG_WARN([Unhandled DRVLIST_NAME=$DRVLIST_NAME])] ) @@ -1178,6 +1185,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_gpio}"; then with_gpio="${withval}"; fi dnl Platform-dependent snowflakes that are required or auto: if test -z "${with_linux_i2c}"; then @@ -1526,6 +1534,20 @@ dnl and AM_CONDITIONALs (see below)... AM_CONDITIONAL(WITH_FREEIPMI, test "${nut_with_freeipmi}" = "yes") dnl AM_CONDITIONAL(WITH_OPENIPMI, test "${nut_with_openipmi}" = "yes") +dnl ---------------------------------------------------------------------- +dnl Check for with-gpio + +nut_gpio_lib="" + +NUT_ARG_WITH([gpio], [build and install GPIO driver], [auto]) + +dnl ${nut_with_gpio}: any value except "yes" or "no" is treated as "auto". +if test "${nut_with_gpio}" != "yes"; then + nut_with_gpio="no" +fi + +NUT_REPORT_FEATURE([build GPIO driver], [${nut_with_gpio}], [${nut_gpio_lib}], + [WITH_GPIO], [Define to enable GPIO support]) dnl ---------------------------------------------------------------------- dnl The Mac OS X meta-driver looks at IOKit Power Sources keys managed by diff --git a/drivers/Makefile.am b/drivers/Makefile.am index d5ebd10229..c9c7daf28c 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -32,6 +32,9 @@ endif if WITH_IPMI AM_CFLAGS += $(LIBIPMI_CFLAGS) endif +if WITH_GPIO + AM_CFLAGS += $(LIBGPIO_CFLAGS) +endif if WITH_MODBUS AM_CFLAGS += $(LIBMODBUS_CFLAGS) endif @@ -56,12 +59,13 @@ MODBUS_DRIVERLIST = phoenixcontact_modbus generic_modbus huawei-ups2000 socomec_ LINUX_I2C_DRIVERLIST = asem pijuice POWERMAN_DRIVERLIST = powerman-pdu IPMI_DRIVERLIST = nut-ipmipsu +GPIO_DRIVERLIST = gpio # distribute all drivers, even ones that are not built by default EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) EXTRA_PROGRAMS += $(SNMP_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST) EXTRA_PROGRAMS += $(LINUX_I2C_DRIVERLIST) -EXTRA_PROGRAMS += $(NUTSW_DRIVERLIST) +EXTRA_PROGRAMS += $(GPIO_DRIVERLIST) # construct the list of drivers to build if SOME_DRIVERS @@ -90,6 +94,9 @@ endif if WITH_IPMI driverexec_PROGRAMS += $(IPMI_DRIVERLIST) endif +if WITH_GPIO + driverexec_PROGRAMS += $(GPIO_DRIVERLIST) +endif if WITH_MACOSX driverexec_PROGRAMS += $(MACOSX_DRIVERLIST) endif @@ -164,6 +171,9 @@ upscode2_LDADD = $(LDADD) -lm victronups_SOURCES = victronups.c riello_ser_SOURCES = riello.c riello_ser.c riello_ser_LDADD = $(LDADD) -lm +gpio_SOURCES = gpio.c +gpio_CFLAGS = $(AM_CFLAGS) +gpio_LDADD = $(LDADD_DRIVERS) -lgpiod # non-serial drivers: these use custom LDADD and/or CFLAGS diff --git a/drivers/gpio.c b/drivers/gpio.c new file mode 100644 index 0000000000..83054d7447 --- /dev/null +++ b/drivers/gpio.c @@ -0,0 +1,645 @@ +/* + anything commented is optional + anything else is mandatory + + for more information, refer to: + * docs/developers.txt + * docs/new-drivers.txt + * docs/new-names.txt + + and possibly also to: + * docs/hid-subdrivers.txt for USB/HID devices + * or docs/snmp-subdrivers.txt for SNMP devices +*/ +/* ./configure --with-pidpath=/run/nut --with-altpidpath=/run/nut --with-statepath=/run/nut --sysconfdir=/etc/nut --with-gpio --with-user=nut --with-group=nut */ +#pragma GCC optimize("O0") + +#include "config.h" +#include "main.h" +#include "attribute.h" +#include "gpio.h" + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "ModrisB ", + DRV_STABLE, + { NULL } +}; + +/* CyberPower 12V open collector state definitions + 0 ON BATTERY Low when operating from utility line + Open when operating from battery + 1 REPLACE BATTERY Low when battery is charged + Open when battery fails the Self Test + 6 BATTERY MISSING Low when battery is present + Open when battery is missing + 3 LOW BATTERY Low when battery is near full charge capacity + Open when operating from a battery with < 20% capacity + + NUT supported states + OL On line (mains is present) + OB On battery (mains is not present) + LB Low battery + HB High battery + RB The battery needs to be replaced + CHRG The battery is charging + DISCHRG The battery is discharging (inverter is providing load power) + BYPASS UPS bypass circuit is active -- no battery protection is available + CAL UPS is currently performing runtime calibration (on battery) + OFF UPS is offline and is not supplying power to the load + OVER UPS is overloaded + TRIM UPS is trimming incoming voltage (called "buck" in some hardware) + BOOST UPS is boosting incoming voltage + FSD Forced Shutdown (restricted use, see the note below) + + CyberPower rules setting + OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; +*/ + +struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; + +static struct gpioups_t *gpio_open(const char *chipName); +static void reserve_lines(struct gpioups_t *gpioupsfd, int inner); +static void gpio_close(struct gpioups_t *upsfd); +static void gpio_get_ups_rules(struct gpioups_t *upsfd); +static void gpio_get_lines_states(struct gpioups_t *gpioupsfd); +static void gpio_set_states(struct gpioups_t *gpioupsfd); + +#undef LOCALTEST +#ifdef LOCALTEST +struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { + NUT_UNUSED_VARIABLE(name); + return (struct gpiod_chip *)1; +} + +unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { + NUT_UNUSED_VARIABLE(chip); + return 32; +} +int gpiod_chip_get_lines(struct gpiod_chip *chip, + unsigned int *offsets, unsigned int num_offsets, + struct gpiod_line_bulk *bulk) { + return 0; +} + +int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, + const struct gpiod_line_request_config *config, + const int *default_vals) +{ + return 0; +} + +int gStatus = 0; + +int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, + int *values) +{ + int pinPos=1; + if(gpioupsfd) + for(int i=0; iupsLinesCount; i++) { + values[i]=(gStatus&pinPos)!=0; + pinPos=pinPos<<1; + } + + gStatus++; + return 0; +} + +int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, + const struct timespec *timeout, + struct gpiod_line_bulk *event_bulk) +{ + switch(gStatus%3) { + case 0: + sleep(2); + break; + case 1: + sleep(4); + break; + case 2: + sleep(6); + break; + } + return 0; +} +#endif + +static void reserve_lines(struct gpioups_t *gpioupsfd, int inner) { + upsdebugx(LOG_DEBUG, "reserve_lines runOptions %d, inner %d", gpioupsfd->runOptions, inner); + if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { + struct gpiod_line_request_config config; + int gpioRc; + config.consumer=upsdrv_info.name; + if(gpioupsfd->runOptions&ROPT_EVMODE) { + config.request_type=GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; + upsdebugx(LOG_DEBUG, "reserve_lines GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); + } else { + config.request_type=GPIOD_LINE_REQUEST_DIRECTION_INPUT; + upsdebugx(LOG_DEBUG, "reserve_lines GPIOD_LINE_REQUEST_DIRECTION_INPUT"); + } + config.flags=0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ + gpioRc=gpiod_line_request_bulk(&gpioupsfd->gpioLines, &config, NULL); + if(gpioRc) + fatal_with_errno( + LOG_ERR, + "GPIO gpiod_line_request_bulk call failed, check for other applications that may have reserved GPIO lines" + ); + upsdebugx( + LOG_DEBUG, + "GPIO gpiod_line_request_bulk with type %d return code %d", + config.request_type, + gpioRc + ); + } +} + +static struct gpioups_t *gpio_open(const char *chipName) { + struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); + upsfdlocal->runOptions=0; /* ROPT_REQRES; ROPT_EVMODE; */ + gpio_get_ups_rules(upsfdlocal); + upsfdlocal->gpioChipHandle=gpiod_chip_open_by_name(chipName); + if(!upsfdlocal->gpioChipHandle) { + fatal_with_errno( + LOG_ERR, + "Could not open GPIO chip [%s], check chips presence and/or access rights", + chipName + ); + } else { + int gpioRc; + upslogx(LOG_NOTICE, "GPIO chip [%s] opened", chipName); + upsfdlocal->chipLinesCount=gpiod_chip_num_lines(upsfdlocal->gpioChipHandle); + upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", upsfdlocal->chipLinesCount, chipName); + if(upsfdlocal->chipLinesCountupsMaxLine) + fatalx( + LOG_ERR, + "GPIO chip lines count %d smaller than UPS line number used (%d)", + upsfdlocal->chipLinesCount, + upsfdlocal->upsMaxLine + ); + upsfdlocal->upsLinesStates=xcalloc(sizeof(int), upsfdlocal->upsLinesCount); + gpiod_line_bulk_init(&upsfdlocal->gpioLines); + gpiod_line_bulk_init(&upsfdlocal->gpioEventLines); + gpioRc=gpiod_chip_get_lines( + upsfdlocal->gpioChipHandle, + (unsigned int *)upsfdlocal->upsLines, + upsfdlocal->upsLinesCount, + &upsfdlocal->gpioLines + ); + if(gpioRc) + fatal_with_errno( + LOG_ERR, + "GPIO line reservation (gpiod_chip_get_lines call) failed with code %d, check for possible issue in rules parameter", + gpioRc + ); + upsdebugx(LOG_DEBUG, "GPIO gpiod_chip_get_lines return code %d", gpioRc); + reserve_lines(upsfdlocal, 0); + } + return upsfdlocal; +} + +static void gpio_close(struct gpioups_t *gpioupsfd) { + if(gpioupsfd) { + if(gpioupsfd->gpioChipHandle) { + gpiod_chip_close(gpioupsfd->gpioChipHandle); + } + if(gpioupsfd->upsLines) { + free(gpioupsfd->upsLines); + } + if(gpioupsfd->upsLinesStates) { + free(gpioupsfd->upsLinesStates); + } + if(gpioupsfd->rules) { + int i; + for(i=0; irulesCount; i++) { + free(gpioupsfd->rules[i]); + } + } + free(gpioupsfd); + } +} + +static void add_rule_item(struct gpioups_t *upsfd, int newValue) { + int subCount=(upsfd->rules[upsfd->rulesCount-1]) ? upsfd->rules[upsfd->rulesCount-1]->subCount+1 : 1; + int itemSize=subCount*sizeof(upsfd->rules[0]->cRules[0])+sizeof(rulesint); + upsfd->rules[upsfd->rulesCount-1]=xrealloc(upsfd->rules[upsfd->rulesCount-1], itemSize); + upsfd->rules[upsfd->rulesCount-1]->subCount=subCount; + upsfd->rules[upsfd->rulesCount-1]->cRules[subCount-1]=newValue; +} + +static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { + static unsigned char lexType[256]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 0x00 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 0x10 */ + 0, 0, 0, 0, 0, 0,'&', 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 0x20 */ + '0','0','0','0','0','0','0','0','0','0', 0,';', 0,'=', 0, 0, /* 48 0x30 */ + 0,'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', /* 64 0x40 */ + 'a','a','a','a','a','a','a','a','a','a','a', 0, 0, 0,'^', 0, /* 80 0x50 */ + 0,'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', /* 96 0x60 */ + 'a','a','a','a','a','a','a','a','a','a','a', 0,'|', 0, 0, 0, /* 112 0x70 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 0x80 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 0x90 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 0xa0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 0xb0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 0xc0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 0xd0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 0xe0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 240 0xf0 */ + }; + unsigned char lexTypeChr=lexType[rulesBuff[*startPos]]; + *endPos=(*startPos)+1; + if(lexTypeChr=='a' || lexTypeChr=='0') { + for(; lexType[rulesBuff[*endPos]]==lexTypeChr; (*endPos)++); + } + return (int)lexTypeChr; +} + +static void gpio_get_ups_rules(struct gpioups_t *upsfd) { + unsigned char *rulesString=(unsigned char *)getval("rules"); + /* statename=[^]line[&||[line]] */ + char lexBuff[33]; + int startPos=0, endPos; + int lexType; + int lexStatus=0; + int i, j, k; + int tranformationDelta; + upsdebugx(LOG_DEBUG, "rules =[%s]", rulesString); + while((lexType=get_rule_lex(rulesString, &startPos, &endPos))>0 && lexStatus>=0) { + memset(lexBuff, 0, sizeof(lexBuff)); + strncpy(lexBuff, (char *)(rulesString+startPos), endPos-startPos); + upsdebugx( + LOG_DEBUG, + "rules start %d, end %d, lexType %d, lex [%s]", + startPos, + endPos, + lexType, + lexBuff + ); + switch(lexStatus) { + case 0: + if(lexType!='a') lexStatus=-1; else { + lexStatus=1; + upsfd->rulesCount++; + upsfd->rules=xrealloc(upsfd->rules, (size_t)(sizeof(upsfd->rules[0])*upsfd->rulesCount)); + upsfd->rules[upsfd->rulesCount-1]=xcalloc(sizeof(rulesint), 1); + strncpy(upsfd->rules[upsfd->rulesCount-1]->stateName, (char *)(rulesString+startPos), endPos-startPos); + upsfd->rules[upsfd->rulesCount-1]->stateName[endPos-startPos]=0; + } + break; + case 1: + if(lexType!='=') lexStatus=-1; else lexStatus=2; + break; + case 2: + if(lexType=='^') { + lexStatus=3; + add_rule_item(upsfd, RULES_CMD_NOT); + } else if(lexType=='0') { + lexStatus=4; + add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); + } else lexStatus=-1; + break; + case 3: + if(lexType!='0') lexStatus=-1; else { + lexStatus=4; + add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); + } + break; + case 4: + if(lexType=='&') { + lexStatus=2; + add_rule_item(upsfd, RULES_CMD_AND); + } else if(lexType=='|') { + lexStatus=2; + add_rule_item(upsfd, RULES_CMD_OR); + } + else if(lexType==';') lexStatus=0; else lexStatus=-1; + break; + default: + lexStatus=-1; + break; + } + if(lexStatus==-1) { + fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); + } + startPos=endPos; + } + + upsdebugx(LOG_DEBUG, "rules count [%d]", upsfd->rulesCount); + for(i=0; irulesCount; i++) { + upsdebugx( + LOG_DEBUG, + "rule state name [%s], + subcount %d", + upsfd->rules[i]->stateName, + upsfd->rules[i]->subCount + ); + for(j=0; jrules[i]->subCount; j++) { + upsdebugx( + LOG_DEBUG, + "[%s] substate %d [%d]", + upsfd->rules[i]->stateName, + j, + upsfd->rules[i]->cRules[j] + ); + } + } + + upsfd->upsLinesCount=0; + upsfd->upsMaxLine=0; + for(i=0; irulesCount; i++) { + for(j=0; jrules[i]->subCount; j++) { + int pinOnList=0; + for(k=0; kupsLinesCount && !pinOnList; k++) { + if(upsfd->upsLines[k]==upsfd->rules[i]->cRules[j]) { + pinOnList=1; + } + } + if(!pinOnList) { + if(upsfd->rules[i]->cRules[j]>=0) { + upsfd->upsLinesCount++; + upsfd->upsLines=xrealloc(upsfd->upsLines, sizeof(upsfd->upsLines[0])*upsfd->upsLinesCount); + upsfd->upsLines[upsfd->upsLinesCount-1]=upsfd->rules[i]->cRules[j]; + if(upsfd->upsLines[upsfd->upsLinesCount-1]>upsfd->upsMaxLine) { + upsfd->upsMaxLine=upsfd->upsLines[upsfd->upsLinesCount-1]; + } + } + } + } + } + + upsdebugx(LOG_DEBUG, "UPS line count = %d", upsfd->upsLinesCount); + for(i=0; iupsLinesCount; i++) { + upsdebugx(LOG_DEBUG, "UPS line%d number %d", i, upsfd->upsLines[i]); + } + + tranformationDelta=upsfd->upsMaxLine-RULES_CMD_LAST+1; + for(i=0; irulesCount; i++) { + for(j=0; jrules[i]->subCount; j++) { + if(upsfd->rules[i]->cRules[j]>=0) { + upsfd->rules[i]->cRules[j]-=tranformationDelta; + } + } + } + for(k=0; kupsLinesCount; k++) { + for(i=0; irulesCount; i++) { + for(j=0; jrules[i]->subCount; j++) { + if((upsfd->rules[i]->cRules[j]+tranformationDelta)==upsfd->upsLines[k]) { + upsfd->rules[i]->cRules[j]=k; + } + } + } + } + upsdebugx(LOG_DEBUG, "rules count [%d] translated", upsfd->rulesCount); + for(i=0; irulesCount; i++) { + upsdebugx( + LOG_DEBUG, + "rule state name [%s], subcount %d translated", + upsfd->rules[i]->stateName, + upsfd->rules[i]->subCount + ); + for(j=0; jrules[i]->subCount; j++) { + upsdebugx( + LOG_DEBUG, + "[%s] substate %d [%d]", + upsfd->rules[i]->stateName, j, + upsfd->rules[i]->cRules[j] + ); + } + } +} + +static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { + int i; + int gpioRc; + reserve_lines(gpioupsfd, 1); + if(gpioupsfd->runOptions&ROPT_EVMODE) { + struct timespec timeoutLong={1,0}; + struct gpiod_line_event event; + int monRes; + upsdebugx( + LOG_DEBUG, + "gpio_get_lines_states initial %d, timeout %ld", + gpioupsfd->initial, + timeoutLong.tv_sec + ); + if(gpioupsfd->initial) { + timeoutLong.tv_sec=35; + } else { + gpioupsfd->initial=1; + } + upsdebugx( + LOG_DEBUG, + "gpio_get_lines_states initial %d, timeout %ld", + gpioupsfd->initial, + timeoutLong.tv_sec + ); + gpiod_line_bulk_init(&gpioupsfd->gpioEventLines); + monRes=gpiod_line_event_wait_bulk( + &gpioupsfd->gpioLines, + &timeoutLong, + &gpioupsfd->gpioEventLines + ); + upsdebugx( + LOG_DEBUG, + "gpiod_line_event_wait_bulk completed with %d return code and timeout %ld s", + monRes, + timeoutLong.tv_sec + ); + if(monRes==1) { + int num_lines=(int)gpiod_line_bulk_num_lines(&gpioupsfd->gpioEventLines); + int i; + for(i=0; igpioEventLines, + i + ); + int eventRc=gpiod_line_event_read(eLine, &event); + unsigned int lineOffset=gpiod_line_offset(eLine); + event.event_type=0; + upsdebugx( + LOG_DEBUG, + "Event read return code %d and event type %d for line %d", + eventRc, + event.event_type, + lineOffset + ); + } + } + } + for(i=0; iupsLinesCount; i++) { + gpioupsfd->upsLinesStates[i]=-1; + } + gpioRc=gpiod_line_get_value_bulk( + &gpioupsfd->gpioLines, + gpioupsfd->upsLinesStates + ); + if (gpioRc<0) + fatal_with_errno(LOG_ERR, "GPIO line status read call failed"); + upsdebugx( + LOG_DEBUG, + "GPIO gpiod_line_get_value_bulk completed with %d return code, status values:", + gpioRc + ); + for(i=0; iupsLinesCount; i++) { + upsdebugx( + LOG_DEBUG, + "Line%d state = %d", + i, + gpioupsfd->upsLinesStates[i] + ); + } + if(gpioupsfd->runOptions&ROPT_REQRES) { + gpiod_line_release_bulk(&gpioupsfd->gpioLines); + } +} + +/* calculate state rule value based on GPIO pin values */ +static int gpio_calc_rule_states(int cRules[], int subCount, int sIndex) { + int ruleVal=0; + int iopStart=sIndex; + int rs; + if(iopStart=0) { + ruleVal=gpioupsfd->upsLinesStates[cRules[iopStart]]; + } else { + iopStart++; + ruleVal=!gpioupsfd->upsLinesStates[cRules[iopStart]]; + } + iopStart++; + } + if(iopStartupsLinesStates[cRules[iopStart]]; + } else { + rs=gpioupsfd->upsLinesStates[cRules[iopStart]]; + } + ruleVal= ruleVal && rs; + } + } + + return ruleVal; +} + +/* set ups state according to rules, do adjustments for CHRG/DISCHRG + and battery charge states */ +static void gpio_set_states(struct gpioups_t *gpioupsfd) { + int batLow=0; + int chargerStatusSet=0; + int ruleNo; + + status_init(); + + for(ruleNo=0; ruleNorulesCount; ruleNo++) { + gpioupsfd->rules[ruleNo]->currVal= + gpio_calc_rule_states( + gpioupsfd->rules[ruleNo]->cRules, + gpioupsfd->rules[ruleNo]->subCount, 0 + ); + if(gpioupsfd->rules[ruleNo]->currVal) { + status_set(gpioupsfd->rules[ruleNo]->stateName); + + if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "CHRG")) { + dstate_setinfo("battery.charger.status", "%s", "charging"); + chargerStatusSet++; + } + if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "DISCHRG")) { + dstate_setinfo("battery.charger.status", "%s", "discharging"); + chargerStatusSet++; + } + if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "LB")) { + batLow=1; + } + } + if(gpioupsfd->aInfoAvailable && + gpioupsfd->rules[ruleNo]->archVal!=gpioupsfd->rules[ruleNo]->currVal) { + upslogx(LOG_WARNING, "UPS state [%s] changed to %d", + gpioupsfd->rules[ruleNo]->stateName, + gpioupsfd->rules[ruleNo]->currVal + ); + } + gpioupsfd->rules[ruleNo]->archVal=gpioupsfd->rules[ruleNo]->currVal; + } + + if(chargerStatusSet<=0) { + dstate_delinfo("battery.charger.status"); + } + + if(dstate_getinfo("battery.charge.low")!=NULL) { + if(batLow) { + dstate_setinfo("battery.charge", "%s", dstate_getinfo("battery.charge.low")); + } else { + dstate_setinfo("battery.charge", "%s", "100"); + } + } + + gpioupsfd->aInfoAvailable=1; + + status_commit(); +} + +void upsdrv_initinfo(void) +{ + if(testvar("mfr")) { + dstate_setinfo("device.mfr", "%s", getval("mfr")); + } + if(testvar("model")) { + dstate_setinfo("device.model", "%s", getval("model")); + } + if(testvar("description")) { + dstate_setinfo("device.description", "%s", getval("description")); + } + + if(!testvar("rules")) /* rules is required configuration parameter */ + fatalx(EXIT_FAILURE, "UPS status calculation rules not specified"); +} + +void upsdrv_updateinfo(void) +{ + /* read GPIO lines states */ + gpio_get_lines_states(gpioupsfd); + + /* calculate/set UPS states based on line values */ + gpio_set_states(gpioupsfd); + + /* no protocol failures possible - mark data as OK */ + dstate_dataok(); +} + +void upsdrv_shutdown(void) + __attribute__((noreturn)); + +void upsdrv_shutdown(void) +{ + fatalx(EXIT_FAILURE, "shutdown not supported"); +} + +void upsdrv_help(void) +{ +} + +/* list flags and values that you want to receive via -x */ +void upsdrv_makevartable(void) +{ + addvar(VAR_SENSITIVE, "mfr", "UPS manufacturer"); + addvar(VAR_SENSITIVE, "model", "UPS model"); + addvar(VAR_VALUE, "rules", "Line rules to produce status strings"); + addvar(VAR_SENSITIVE, "description", "Device description"); + addvar(VAR_SENSITIVE, "desc", "Device description"); +} + +void upsdrv_initups(void) +{ + /* open GPIO chip and check pin consistence */ + gpioupsfd=gpio_open(device_path); +} + +void upsdrv_cleanup(void) +{ + /* close GPIO chip and release related resources */ + gpio_close(gpioupsfd); +} \ No newline at end of file From 78a3b2031efebf2f6f29d1e24c989e2974bf9bd5 Mon Sep 17 00:00:00 2001 From: modrisb Date: Mon, 20 Feb 2023 21:45:07 +0200 Subject: [PATCH 0465/1232] initial for GPIO(2) --- drivers/gpio.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 drivers/gpio.h diff --git a/drivers/gpio.h b/drivers/gpio.h new file mode 100644 index 0000000000..c80a087b82 --- /dev/null +++ b/drivers/gpio.h @@ -0,0 +1,48 @@ +#ifndef GPIO_H +#define GPIO_H + +#include +#include +#include +#include + +#define DRIVER_NAME "GPIO UPS driver" +#define DRIVER_VERSION "0.09" + +/* rules command definition */ +#define RULES_CMD_NOT -2 +#define RULES_CMD_AND -3 +#define RULES_CMD_OR -4 +#define RULES_CMD_OBR -5 +#define RULES_CMD_CBR -6 +#define RULES_CMD_LAST RULES_CMD_CBR + +/* run option definitions */ +#define ROPT_REQRES 0x00000001 /* reserve GPIO lines only during request processing */ +#define ROPT_EVMODE 0x00000002 /* event driven run */ + +typedef struct rulesint_t { + char stateName[12]; + int archVal; + int currVal; + int subCount; + int cRules[]; +} rulesint; + +typedef struct gpioups_t { + struct gpiod_chip *gpioChipHandle; + struct gpiod_line_bulk gpioLines; + struct gpiod_line_bulk gpioEventLines; + int initial; + int runOptions; + int aInfoAvailable; + int chipLinesCount; + int upsLinesCount; + int *upsLines; + int *upsLinesStates; + int upsMaxLine; + int rulesCount; + struct rulesint_t **rules; +} gpioups; + +#endif /* GPIO_H */ \ No newline at end of file From fa6d29b6425f2c02ed4a518cd904eb1e3520a26f Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 22 Feb 2023 10:44:57 +0200 Subject: [PATCH 0466/1232] added draft man page --- docs/man/gpio.txt | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/man/gpio.txt diff --git a/docs/man/gpio.txt b/docs/man/gpio.txt new file mode 100644 index 0000000000..f4b03e33e9 --- /dev/null +++ b/docs/man/gpio.txt @@ -0,0 +1,99 @@ +GPIO(8) +================= + +NAME +---- + +GPIO - Driver for GPIO connected UPS + +SYNOPSIS +-------- + +*GPIO* -h + +*GPIO* -a 'GPIOCHIP0' ['OPTIONS'] + +NOTE: This man page only documents the specific features of the *GPIO* +driver. For information about the core driver, see linkman:nutupsdrv[8]. + +SUPPORTED HARDWARE +------------------ + +This is the driver for GPIO attached UPS devices. + +The driver has been tested against CyberPower CyberShield CSN27U12V attached +Orange Pi Zero GPIO. + +More information about this UPS can be found here: :: +https://www.cyberpowersystems.com/resources/csn27u12v-um/ + + +EXTRA ARGUMENTS +--------------- + +This driver supports the following optional settings in the +linkman:ups.conf[5] file: + +Driver control: +~~~~~~~~~~~~~~ + +*rules*='value':: +A string consisting of substrings. Each substring describes GPIO line states conversion formula to specific NUT state, like nut_state=[^]line_num[logical_operationline_num]. And (&) and or (|) operations are supported for now. + +Battery Charge: +~~~~~~~~~~~~~~ + +*default.battery.charge.low*='value':: +An integer specifying the battery charge level reported in LB case. + + +CONFIGURATION +------------- + +Here is an example of GPIO driver configuration in *ups.conf* file: +---- +[CyberPower12v] + driver = GPIO + port = gpiochip0 + description = "Modem and DNS server UPS" + mfr = CyberPower + model = "CyberShield CSN27U12V" + rules = "OL=^0;OB=0;LB=3;RB=1;DISCHRG=0&^6;BYPASS=6;" + default.battery.charge.low = 20 +---- + +SHTDOWN COMMAND +---------------- + +This driver does not support shutdown command. + +INSTALLATION +------------ + +This driver is not built by default. You can build it by installing +libgpiod and running `configure --with-gpio=yes`. + +You also need to give proper permissions on the local serial device +file (/dev/gpiochip0 for example) to allow the run-time NUT driver user +account to access it, like by adding the following rule to rules.d directory: +SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ + chown -R nut:nut /dev/gpiochip0 && chmod -R 700 /dev/gpiochip0\ + +AUTHOR +------ + +Modris Berzonis + +SEE ALSO +-------- + +The core driver: +~~~~~~~~~~~~~~~~ + +linkman:nutupsdrv[8], linkman:ups.conf[5] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ + +* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* libmodbus home page: http://libmodbus.org From 2a8e126099a0b8a1cc36d444e38d6f8e8536666f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 11:26:11 +0100 Subject: [PATCH 0467/1232] configure.ac, common/common.c nut_report_config_flags(): track and report NUT_SOURCE_GITREV if available (even where nut_version.h imposes strict version) --- common/common.c | 33 +++++++++++++++++++++++++++++---- configure.ac | 16 ++++++++++------ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/common/common.c b/common/common.c index fff7532a00..3f2052e09f 100644 --- a/common/common.c +++ b/common/common.c @@ -944,18 +944,43 @@ void nut_report_config_flags(void) * Depending on amount of configuration tunables involved by a particular * build of NUT, the string can be quite long (over 1KB). */ + char *gitrev = NULL; if (nut_debug_level < 1) return; + /* Only report git revision if remarkably different from UPS_VERSION + * which may be e.g. "2.8.0.1" or already include the source revision + * as decided when generating nut_version.h (and if it was re-generated + * in case of rebuilds while developers are locally iterating). + * If the same version string is indeed present, gitrev is "v". + */ + if (NUT_SOURCE_GITREV && UPS_VERSION && + (strlen(UPS_VERSION) < 12 || !strstr(NUT_SOURCE_GITREV, UPS_VERSION)) + ) { + /* If UPS_VERSION is too short (so likely a static string + * from configure.ac AC_INIT() -- although some distros, + * especially embedders, tend to place their product IDs here), + * or if it is NOT a substring of NUT_SOURCE_GITREV: */ + gitrev = NUT_SOURCE_GITREV; + } + if (xbit_test(upslog_flags, UPSLOG_STDERR)) - fprintf(stderr, "Network UPS Tools version %s configured with flags: %s\n", - UPS_VERSION, CONFIG_FLAGS); + fprintf(stderr, "Network UPS Tools version %s%s%s%s configured with flags: %s\n", + UPS_VERSION, + (gitrev ? " (git revision " : ""), + (gitrev ? gitrev : ""), + (gitrev ? ")" : ""), + CONFIG_FLAGS); /* NOTE: May be ignored or truncated by receiver if that syslog server * (and/or OS sender) does not accept messages of such length */ if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) - syslog(LOG_DEBUG, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s configured with flags: %s", + UPS_VERSION, + (gitrev ? " (git revision " : ""), + (gitrev ? gitrev : ""), + (gitrev ? ")" : ""), + CONFIG_FLAGS); } static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) diff --git a/configure.ac b/configure.ac index 550ec77a1d..faddbd1d9c 100644 --- a/configure.ac +++ b/configure.ac @@ -12,8 +12,12 @@ dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ. (command -v git >/dev/null 2>/dev/null) \ -&& GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ -|| GITREV="" +&& NUT_SOURCE_GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ +|| NUT_SOURCE_GITREV="" + +AS_IF([test -n "${NUT_SOURCE_GITREV-}"], + [AC_DEFINE_UNQUOTED([NUT_SOURCE_GITREV], ["${NUT_SOURCE_GITREV}"], [NUT source revision when the build was configured])], + [AC_DEFINE([NUT_SOURCE_GITREV], [NULL], [NUT source revision when the build was configured: not detected])]) dnl Keep track of command-line options passed to this script: AC_MSG_CHECKING([for CONFIG_FLAGS]) @@ -62,9 +66,9 @@ AC_SUBST(CONFIG_FLAGS) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_SRCDIR(server/upsd.c) AC_CONFIG_MACRO_DIR([m4]) -AS_IF([test x"${GITREV}" = x], +AS_IF([test x"${NUT_SOURCE_GITREV}" = x], [echo "Network UPS Tools version ${PACKAGE_VERSION}"], - [echo "Network UPS Tools version ${PACKAGE_VERSION} (${GITREV})"]) + [echo "Network UPS Tools version ${PACKAGE_VERSION} (${NUT_SOURCE_GITREV})"]) AC_CANONICAL_TARGET NUT_CHECK_OS NUT_STASH_WARNINGS @@ -376,9 +380,9 @@ NUT_ARG_ENABLE([keep_nut_report_feature], [Request that we keep config.nut_report_feature.log (normally deleted by configure script after displaying)], [no]) -AS_IF([test x"${GITREV}" = x], +AS_IF([test x"${NUT_SOURCE_GITREV}" = x], [NUT_REPORT([configured version], [${PACKAGE_VERSION}])], - [NUT_REPORT([configured version], [${PACKAGE_VERSION} (${GITREV})])]) + [NUT_REPORT([configured version], [${PACKAGE_VERSION} (${NUT_SOURCE_GITREV})])]) dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase: NUT_COMPILER_FAMILY From b5600fa5f838409330caf793cef5169020602b24 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 12:00:17 +0100 Subject: [PATCH 0468/1232] configure.ac: actually, we should not forcefully export NUT_SOURCE_GITREV into config.h --- common/common.c | 33 ++++++++++++++++++--------------- configure.ac | 11 ++++++++--- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/common/common.c b/common/common.c index 3f2052e09f..440662a4a7 100644 --- a/common/common.c +++ b/common/common.c @@ -944,32 +944,35 @@ void nut_report_config_flags(void) * Depending on amount of configuration tunables involved by a particular * build of NUT, the string can be quite long (over 1KB). */ - char *gitrev = NULL; + char *relver = NULL; if (nut_debug_level < 1) return; - /* Only report git revision if remarkably different from UPS_VERSION - * which may be e.g. "2.8.0.1" or already include the source revision + /* Only report git revision if NUT_VERSION_MACRO in nut_version.h aka + * UPS_VERSION here is remarkably different from PACKAGE_VERSION from + * configure.ac AC_INIT() -- which may be e.g. "2.8.0.1" although some + * distros, especially embedders, tend to place their product IDs here). + * The macro may be that fixed version or refer to git source revision, * as decided when generating nut_version.h (and if it was re-generated - * in case of rebuilds while developers are locally iterating). - * If the same version string is indeed present, gitrev is "v". + * in case of rebuilds while developers are locally iterating -- this + * may be disabled for faster local iterations at a cost of a little lie). */ - if (NUT_SOURCE_GITREV && UPS_VERSION && - (strlen(UPS_VERSION) < 12 || !strstr(NUT_SOURCE_GITREV, UPS_VERSION)) + if (PACKAGE_VERSION && UPS_VERSION && + (strlen(UPS_VERSION) < 12 || !strstr(UPS_VERSION, PACKAGE_VERSION)) ) { /* If UPS_VERSION is too short (so likely a static string * from configure.ac AC_INIT() -- although some distros, * especially embedders, tend to place their product IDs here), - * or if it is NOT a substring of NUT_SOURCE_GITREV: */ - gitrev = NUT_SOURCE_GITREV; + * or if PACKAGE_VERSION *is NOT* a substring of it: */ + relver = PACKAGE_VERSION; } if (xbit_test(upslog_flags, UPSLOG_STDERR)) fprintf(stderr, "Network UPS Tools version %s%s%s%s configured with flags: %s\n", UPS_VERSION, - (gitrev ? " (git revision " : ""), - (gitrev ? gitrev : ""), - (gitrev ? ")" : ""), + (relver ? " (release/snapshot of " : ""), + (relver ? relver : ""), + (relver ? ")" : ""), CONFIG_FLAGS); /* NOTE: May be ignored or truncated by receiver if that syslog server @@ -977,9 +980,9 @@ void nut_report_config_flags(void) if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s configured with flags: %s", UPS_VERSION, - (gitrev ? " (git revision " : ""), - (gitrev ? gitrev : ""), - (gitrev ? ")" : ""), + (relver ? " (release/snapshot of " : ""), + (relver ? relver : ""), + (relver ? ")" : ""), CONFIG_FLAGS); } diff --git a/configure.ac b/configure.ac index faddbd1d9c..0aaf950c7e 100644 --- a/configure.ac +++ b/configure.ac @@ -15,9 +15,14 @@ dnl without reconfiguration, detailed version in the binaries will differ. && NUT_SOURCE_GITREV="`git describe --tags 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" -AS_IF([test -n "${NUT_SOURCE_GITREV-}"], - [AC_DEFINE_UNQUOTED([NUT_SOURCE_GITREV], ["${NUT_SOURCE_GITREV}"], [NUT source revision when the build was configured])], - [AC_DEFINE([NUT_SOURCE_GITREV], [NULL], [NUT source revision when the build was configured: not detected])]) +dnl Note: except for experiments, do not pass this into config.h - use +dnl the NUT_VERSION_MACRO from nut_version.h instead. Developers may +dnl want to disable their "force-nut-version-header" configure option +dnl to reduce rebuild scope and so speed up the iterations with ccache. +dnl New "config.h" contents for every reconfig would defeat that purpose! +dnl ### AS_IF([test -n "${NUT_SOURCE_GITREV-}"], +dnl ### [AC_DEFINE_UNQUOTED([NUT_SOURCE_GITREV], ["${NUT_SOURCE_GITREV}"], [NUT source revision when the build was configured])], +dnl ### [AC_DEFINE([NUT_SOURCE_GITREV], [NULL], [NUT source revision when the build was configured: not detected])]) dnl Keep track of command-line options passed to this script: AC_MSG_CHECKING([for CONFIG_FLAGS]) From 42d934b75ca94c9a5917439d50abd99d26869781 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 13:32:52 +0100 Subject: [PATCH 0469/1232] configure.ac, m4/nut_compiler_family.m4: minimize executions of "CC --version" etc, make it LANG-agnostic, cache as CC_VERSION etc. --- configure.ac | 7 ++--- m4/nut_compiler_family.m4 | 65 ++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 0aaf950c7e..9f66a846ed 100644 --- a/configure.ac +++ b/configure.ac @@ -3067,9 +3067,8 @@ AS_IF([test x"$have_PKG_CONFIG" = xyes], AS_IF([test "${have_cppunit}" != "yes"], [AC_MSG_WARN([libcppunit not found - those C++ tests will not be built.]) have_cppunit=no], - [AS_IF([test -n "$CXX"], - [AS_IF([$CXX --version 2>&1 | grep 'Free Software Foundation' > /dev/null], - [CPPUNIT_NUT_CXXFLAGS="-g -O0"])]) + [AS_IF([test "x$GXX" = xyes], + [CPPUNIT_NUT_CXXFLAGS="-g -O0"]) ]) ]) ], [AC_MSG_WARN([pkg-config not found, can not look properly for libcppunit - those C++ tests will not be built.]) @@ -3721,7 +3720,7 @@ AS_CASE(["${nut_enable_warnings}"], [AS_IF([test "${GCC}" = "yes"], [ AS_CASE(["${CFLAGS}"], [*89*|*90*|*ansi*], [nut_enable_warnings="gcc-minimal"], - [AS_CASE(["`$CC --version | grep -i gcc`"], + [AS_CASE(["$CC_VERSION"], [*" "1.*|*" "2.*|3.*|*" "4.0*|*" "4.1*|*" "4.2*|*" "4.3*], [ AC_MSG_WARN([Very old GCC in use, disabling warnings]) dnl #AS_IF([test x"${nut_enable_Werror}" = xauto], [nut_enable_Werror="no"]) diff --git a/m4/nut_compiler_family.m4 b/m4/nut_compiler_family.m4 index 8cdc972b95..f47b1ae995 100644 --- a/m4/nut_compiler_family.m4 +++ b/m4/nut_compiler_family.m4 @@ -2,61 +2,90 @@ dnl detect if current compiler is clang or gcc (or...) AC_DEFUN([NUT_COMPILER_FAMILY], [ + CC_VERSION_FULL="`LANG=C LC_ALL=C $CC --version 2>&1`" || CC_VERSION_FULL="" + CXX_VERSION_FULL="`LANG=C LC_ALL=C $CXX --version 2>&1`" || CXX_VERSION_FULL="" + CPP_VERSION_FULL="`LANG=C LC_ALL=C $CPP --version 2>&1`" || CPP_VERSION_FULL="" + CC_VERSION="" + CXX_VERSION="" + CPP_VERSION="" + AC_CACHE_CHECK([if CC compiler family is GCC], [nut_cv_GCC], - [AS_IF([test -n "$CC"], - [AS_IF([$CC --version 2>&1 | grep 'Free Software Foundation' > /dev/null], + [AS_IF([test -n "$CC" && test -n "$CC_VERSION_FULL"], + [AS_IF([echo "${CC_VERSION_FULL}" | grep 'Free Software Foundation' > /dev/null], [nut_cv_GCC=yes],[nut_cv_GCC=no])], [AC_MSG_ERROR([CC is not set])] )]) AC_CACHE_CHECK([if CXX compiler family is GCC], [nut_cv_GXX], - [AS_IF([test -n "$CXX"], - [AS_IF([$CXX --version 2>&1 | grep 'Free Software Foundation' > /dev/null], + [AS_IF([test -n "$CXX" && test -n "$CXX_VERSION_FULL"], + [AS_IF([echo "${CXX_VERSION_FULL}" | grep 'Free Software Foundation' > /dev/null], [nut_cv_GXX=yes],[nut_cv_GXX=no])], [AC_MSG_ERROR([CXX is not set])] )]) AC_CACHE_CHECK([if CPP preprocessor family is GCC], [nut_cv_GPP], - [AS_IF([test -n "$CPP"], - [AS_IF([$CPP --version 2>&1 | grep 'Free Software Foundation' > /dev/null], + [AS_IF([test -n "$CPP" && test -n "$CPP_VERSION_FULL"], + [AS_IF([echo "${CPP_VERSION_FULL}" | grep 'Free Software Foundation' > /dev/null], [nut_cv_GPP=yes],[nut_cv_GPP=no])], [AC_MSG_ERROR([CPP is not set])] )]) - AS_IF([test "x$GCC" = "x" && test "$nut_cv_GCC" = yes], [GCC=yes]) - AS_IF([test "x$GXX" = "x" && test "$nut_cv_GXX" = yes], [GXX=yes]) - AS_IF([test "x$GPP" = "x" && test "$nut_cv_GPP" = yes], [GPP=yes]) + AS_IF([test "x$GCC" = "x" && test "$nut_cv_GCC" = yes], [GCC=yes + CC_VERSION="`echo "${CC_VERSION_FULL}" | grep -i gcc | head -1`" \ + && test -n "${CC_VERSION}" || CC_VERSION="" + ]) + AS_IF([test "x$GXX" = "x" && test "$nut_cv_GXX" = yes], [GXX=yes + CXX_VERSION="`echo "${CXX_VERSION_FULL}" | grep -i -E 'g++|gcc' | head -1`" \ + && test -n "${CXX_VERSION}" || CXX_VERSION="" + ]) + AS_IF([test "x$GPP" = "x" && test "$nut_cv_GPP" = yes], [GPP=yes + CPP_VERSION="`echo "${CPP_VERSION_FULL}" | grep -i -E 'cpp|gcc' | head -1`" \ + && test -n "${CPP_VERSION}" || CPP_VERSION="" + ]) AC_CACHE_CHECK([if CC compiler family is clang], [nut_cv_CLANGCC], - [AS_IF([test -n "$CC"], - [AS_IF([$CC --version 2>&1 | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], + [AS_IF([test -n "$CC" && test -n "$CC_VERSION_FULL"], + [AS_IF([echo "${CC_VERSION_FULL}" | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], [nut_cv_CLANGCC=yes],[nut_cv_CLANGCC=no])], [AC_MSG_ERROR([CC is not set])] )]) AC_CACHE_CHECK([if CXX compiler family is clang], [nut_cv_CLANGXX], - [AS_IF([test -n "$CXX"], - [AS_IF([$CXX --version 2>&1 | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], + [AS_IF([test -n "$CXX" && test -n "$CXX_VERSION_FULL"], + [AS_IF([echo "${CXX_VERSION_FULL}" | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], [nut_cv_CLANGXX=yes],[nut_cv_CLANGXX=no])], [AC_MSG_ERROR([CXX is not set])] )]) AC_CACHE_CHECK([if CPP preprocessor family is clang], [nut_cv_CLANGPP], - [AS_IF([test -n "$CPP"], - [AS_IF([$CPP --version 2>&1 | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], + [AS_IF([test -n "$CPP" && test -n "$CPP_VERSION_FULL"], + [AS_IF([echo "${CPP_VERSION_FULL}" | grep -E '(clang version|Apple LLVM version .*clang-)' > /dev/null], [nut_cv_CLANGPP=yes],[nut_cv_CLANGPP=no])], [AC_MSG_ERROR([CPP is not set])] )]) - AS_IF([test "x$CLANGCC" = "x" && test "$nut_cv_CLANGCC" = yes], [CLANGCC=yes]) - AS_IF([test "x$CLANGXX" = "x" && test "$nut_cv_CLANGXX" = yes], [CLANGXX=yes]) - AS_IF([test "x$CLANGPP" = "x" && test "$nut_cv_CLANGPP" = yes], [CLANGPP=yes]) + AS_IF([test "x$CLANGCC" = "x" && test "$nut_cv_CLANGCC" = yes], [CLANGCC=yes + CC_VERSION="`echo "${CC_VERSION_FULL}" | grep -v "Dir:" | tr '\n' ';' | sed -e 's, *;,;,g' -e 's,;$,,' -e 's,;,; ,g'`" \ + && test -n "${CC_VERSION}" || CC_VERSION="" + ]) + AS_IF([test "x$CLANGXX" = "x" && test "$nut_cv_CLANGXX" = yes], [CLANGXX=yes + CXX_VERSION="`echo "${CXX_VERSION_FULL}" | grep -v "Dir:" | tr '\n' ';' | sed -e 's, *;,;,g' -e 's,;$,,' -e 's,;,; ,g'`" \ + && test -n "${CXX_VERSION}" || CXX_VERSION="" + ]) + AS_IF([test "x$CLANGPP" = "x" && test "$nut_cv_CLANGPP" = yes], [CLANGPP=yes + CPP_VERSION="`echo "${CPP_VERSION_FULL}" | grep -v "Dir:" | tr '\n' ';' | sed -e 's, *;,;,g' -e 's,;$,,' -e 's,;,; ,g'`" \ + && test -n "${CPP_VERSION}" || CPP_VERSION="" + ]) + + AS_IF([test "x$CC_VERSION" = x], [CC_VERSION="`echo "${CC_VERSION_FULL}" | head -1`"]) + AS_IF([test "x$CXX_VERSION" = x], [CXX_VERSION="`echo "${CXX_VERSION_FULL}" | head -1`"]) + AS_IF([test "x$CPP_VERSION" = x], [CPP_VERSION="`echo "${CPP_VERSION_FULL}" | head -1`"]) ]) AC_DEFUN([NUT_CHECK_COMPILE_FLAG], From 5f75056ca23f398abdb57468d550c232704d89a0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 13:38:58 +0100 Subject: [PATCH 0470/1232] configure.ac: report CC_VERSION (also into config.h) --- configure.ac | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.ac b/configure.ac index 9f66a846ed..8007ade57f 100644 --- a/configure.ac +++ b/configure.ac @@ -391,6 +391,15 @@ AS_IF([test x"${NUT_SOURCE_GITREV}" = x], dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase: NUT_COMPILER_FAMILY + +dnl Note: DO NOT AC_DEFINE the "FULL" items: they are generally multi-line. +dnl NUT_REPORT_TARGET([CC_VERSION_FULL], [${CC_VERSION_FULL}], [Version and other details of C compiler]) +dnl NUT_REPORT_TARGET([CXX_VERSION_FULL], [${CXX_VERSION_FULL}], [Version and other details of C++ compiler]) +dnl NUT_REPORT_TARGET([CPP_VERSION_FULL], [${CPP_VERSION_FULL}], [Version and other details of C preprocessor]) +NUT_REPORT_TARGET([CC_VERSION], [${CC_VERSION}], [Compact version of C compiler]) +NUT_REPORT_TARGET([CXX_VERSION], [${CXX_VERSION}], [Compact version of C++ compiler]) +NUT_REPORT_TARGET([CPP_VERSION], [${CPP_VERSION}], [Compact version of C preprocessor]) + dnl Help find warning/error details in a wall of text (must be processed before NUT_COMPILER_FAMILY_FLAGS): NUT_ARG_ENABLE([Wcolor], [Request that compiler output is colorized (no = leave it up to compiler defaults)], From caec18b0e7bbf03535f52987919293db5ae21fac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 13:42:03 +0100 Subject: [PATCH 0471/1232] common/common.c: nut_report_config_flags(): report CC_VERSION if available --- common/common.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index 440662a4a7..55bad80708 100644 --- a/common/common.c +++ b/common/common.c @@ -968,21 +968,27 @@ void nut_report_config_flags(void) } if (xbit_test(upslog_flags, UPSLOG_STDERR)) - fprintf(stderr, "Network UPS Tools version %s%s%s%s configured with flags: %s\n", + fprintf(stderr, "Network UPS Tools version %s%s%s%s%s%s%s configured with flags: %s\n", UPS_VERSION, (relver ? " (release/snapshot of " : ""), (relver ? relver : ""), (relver ? ")" : ""), + (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), + (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), + (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), CONFIG_FLAGS); /* NOTE: May be ignored or truncated by receiver if that syslog server * (and/or OS sender) does not accept messages of such length */ if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) - syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s configured with flags: %s", + syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s%s%s%s configured with flags: %s", UPS_VERSION, (relver ? " (release/snapshot of " : ""), (relver ? relver : ""), (relver ? ")" : ""), + (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), + (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), + (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), CONFIG_FLAGS); } From 3eafd9cfb0cb34a25e1c4724e69223c1ad21189f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 14:03:40 +0100 Subject: [PATCH 0472/1232] m4/nut_report_feature.m4: fix printf() reporting of potentially "funny" strings --- m4/nut_report_feature.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index 31814c2ce2..c324f20e4e 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -24,7 +24,7 @@ AC_DEFUN([NUT_REPORT_FILE], echo "" fi > "config.nut_report_feature.log.$3" ]) - printf "* $1:\t$2\n" >> "config.nut_report_feature.log.$3" + printf "* %s:\t%s\n" "$1" "$2" >> "config.nut_report_feature.log.$3" ]) AC_DEFUN([NUT_REPORT], From ddb4949891d647ffb6bad5df950d3adcd7bfff3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 14:17:05 +0100 Subject: [PATCH 0473/1232] fixup! configure.ac: report CC_VERSION (also into config.h) --- configure.ac | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 8007ade57f..16f9f8e15a 100644 --- a/configure.ac +++ b/configure.ac @@ -393,12 +393,12 @@ dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase: NUT_COMPILER_FAMILY dnl Note: DO NOT AC_DEFINE the "FULL" items: they are generally multi-line. -dnl NUT_REPORT_TARGET([CC_VERSION_FULL], [${CC_VERSION_FULL}], [Version and other details of C compiler]) -dnl NUT_REPORT_TARGET([CXX_VERSION_FULL], [${CXX_VERSION_FULL}], [Version and other details of C++ compiler]) -dnl NUT_REPORT_TARGET([CPP_VERSION_FULL], [${CPP_VERSION_FULL}], [Version and other details of C preprocessor]) -NUT_REPORT_TARGET([CC_VERSION], [${CC_VERSION}], [Compact version of C compiler]) -NUT_REPORT_TARGET([CXX_VERSION], [${CXX_VERSION}], [Compact version of C++ compiler]) -NUT_REPORT_TARGET([CPP_VERSION], [${CPP_VERSION}], [Compact version of C preprocessor]) +dnl NUT_REPORT_TARGET([CC_VERSION_FULL], ["${CC_VERSION_FULL}"], [Version and other details of C compiler]) +dnl NUT_REPORT_TARGET([CXX_VERSION_FULL], ["${CXX_VERSION_FULL}"], [Version and other details of C++ compiler]) +dnl NUT_REPORT_TARGET([CPP_VERSION_FULL], ["${CPP_VERSION_FULL}"], [Version and other details of C preprocessor]) +NUT_REPORT_TARGET([CC_VERSION], ["${CC_VERSION}"], [Compact version of C compiler]) +NUT_REPORT_TARGET([CXX_VERSION], ["${CXX_VERSION}"], [Compact version of C++ compiler]) +NUT_REPORT_TARGET([CPP_VERSION], ["${CPP_VERSION}"], [Compact version of C preprocessor]) dnl Help find warning/error details in a wall of text (must be processed before NUT_COMPILER_FAMILY_FLAGS): NUT_ARG_ENABLE([Wcolor], From 973897646000cb50f94652fb584d0f3dc7d042e6 Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 22 Feb 2023 15:19:14 +0200 Subject: [PATCH 0474/1232] preparing for PR --- docs/man/gpio.txt | 25 ++++++++++++++++++++++--- drivers/gpio.c | 44 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/docs/man/gpio.txt b/docs/man/gpio.txt index f4b03e33e9..be16215300 100644 --- a/docs/man/gpio.txt +++ b/docs/man/gpio.txt @@ -38,7 +38,26 @@ Driver control: ~~~~~~~~~~~~~~ *rules*='value':: -A string consisting of substrings. Each substring describes GPIO line states conversion formula to specific NUT state, like nut_state=[^]line_num[logical_operationline_num]. And (&) and or (|) operations are supported for now. +A string consisting of substrings. Each substring describes GPIO line +states conversion formula to specific NUT state, like +nut_state=[^]line_num[logical_operationline_num]. Not (^) , and (&) , or +(|)operations are supported for now. nut_state should correspond to NUT +state, line_num to GPIO line number connected to UPS open collector pin. +CyberShield CSN27U12V describes pins as: +ON BATTERY Low when operating from utility line + Open when operating from battery +REPLACE BATTERY Low when battery is charged + Open when battery fails the Self Test +BATTERY MISSING Low when battery is present + Open when battery is missing +LOW BATTERY Low when battery is near full charge capacity + Open when operating from a battery with < 20% capacity +and rules migh be defined as +rules = "OL=^0;OB=0;LB=3;RB=1;DISCHRG=0&^6;BYPASS=6;" +assuming that line 0 is connected to ON BATTERY pin, REPLACE BATTERY to line 1, +BATTERY MISSING pin to line 6 and LOW BATTERY to line 3. Expecting simple formula +to be used for each state, extra may increase state reliability and may need to be +checked on each specific UPS. Battery Charge: ~~~~~~~~~~~~~~ @@ -63,7 +82,7 @@ Here is an example of GPIO driver configuration in *ups.conf* file: ---- SHTDOWN COMMAND ----------------- +--------------- This driver does not support shutdown command. @@ -96,4 +115,4 @@ Internet resources: ~~~~~~~~~~~~~~~~~~~ * The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ -* libmodbus home page: http://libmodbus.org +* libgpiod home page: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/ diff --git a/drivers/gpio.c b/drivers/gpio.c index 83054d7447..9ecdebd2ae 100644 --- a/drivers/gpio.c +++ b/drivers/gpio.c @@ -126,6 +126,8 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, } #endif +/* reserve GPIO lines as per run options and inner parameter: do reservation once + or per each status read */ static void reserve_lines(struct gpioups_t *gpioupsfd, int inner) { upsdebugx(LOG_DEBUG, "reserve_lines runOptions %d, inner %d", gpioupsfd->runOptions, inner); if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { @@ -155,9 +157,10 @@ static void reserve_lines(struct gpioups_t *gpioupsfd, int inner) { } } +/* open gpiochip, process rules and check lines numbers validity */ static struct gpioups_t *gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); - upsfdlocal->runOptions=0; /* ROPT_REQRES; ROPT_EVMODE; */ + upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ gpio_get_ups_rules(upsfdlocal); upsfdlocal->gpioChipHandle=gpiod_chip_open_by_name(chipName); if(!upsfdlocal->gpioChipHandle) { @@ -199,6 +202,7 @@ static struct gpioups_t *gpio_open(const char *chipName) { return upsfdlocal; } +/* close gpiochip and release any allocated resources */ static void gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd) { if(gpioupsfd->gpioChipHandle) { @@ -213,6 +217,9 @@ static void gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd->rules) { int i; for(i=0; irulesCount; i++) { + if(gpioupsfd->rules[i].cRules) { + free(gpioupsfd->rules[i].cRules); + } free(gpioupsfd->rules[i]); } } @@ -220,6 +227,7 @@ static void gpio_close(struct gpioups_t *gpioupsfd) { } } +/* add compiled subrules item to the array */ static void add_rule_item(struct gpioups_t *upsfd, int newValue) { int subCount=(upsfd->rules[upsfd->rulesCount-1]) ? upsfd->rules[upsfd->rulesCount-1]->subCount+1 : 1; int itemSize=subCount*sizeof(upsfd->rules[0]->cRules[0])+sizeof(rulesint); @@ -228,6 +236,9 @@ static void add_rule_item(struct gpioups_t *upsfd, int newValue) { upsfd->rules[upsfd->rulesCount-1]->cRules[subCount-1]=newValue; } +/* get next lexem out of rules configuration string recognizing separators = and ; , +logical commands ^ , & , | , state names - several ascii characters matching NUT states, +and several numbers to denote GPIO chip lines to read statuses */ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { static unsigned char lexType[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 0x00 */ @@ -255,6 +266,7 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { return (int)lexTypeChr; } +/* split subrules and translate them to array of commands/line numbers */ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { unsigned char *rulesString=(unsigned char *)getval("rules"); /* statename=[^]line[&||[line]] */ @@ -278,7 +290,9 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { ); switch(lexStatus) { case 0: - if(lexType!='a') lexStatus=-1; else { + if(lexType!='a') { + lexStatus=-1; + } else { lexStatus=1; upsfd->rulesCount++; upsfd->rules=xrealloc(upsfd->rules, (size_t)(sizeof(upsfd->rules[0])*upsfd->rulesCount)); @@ -288,7 +302,11 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { } break; case 1: - if(lexType!='=') lexStatus=-1; else lexStatus=2; + if(lexType!='=') { + lexStatus=-1; + } else { + lexStatus=2; + } break; case 2: if(lexType=='^') { @@ -297,10 +315,14 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { } else if(lexType=='0') { lexStatus=4; add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); - } else lexStatus=-1; + } else { + lexStatus=-1; + } break; case 3: - if(lexType!='0') lexStatus=-1; else { + if(lexType!='0') { + lexStatus=-1; + } else { lexStatus=4; add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); } @@ -313,15 +335,18 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { lexStatus=2; add_rule_item(upsfd, RULES_CMD_OR); } - else if(lexType==';') lexStatus=0; else lexStatus=-1; + else if(lexType==';') { + lexStatus=0; + } else { + lexStatus=-1; + } break; default: lexStatus=-1; break; } - if(lexStatus==-1) { + if(lexStatus==-1) fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); - } startPos=endPos; } @@ -409,6 +434,7 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { } } +/* get GPIO line states for all needed lines */ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { int i; int gpioRc; @@ -494,7 +520,7 @@ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { } } -/* calculate state rule value based on GPIO pin values */ +/* calculate state rule value based on GPIO line values */ static int gpio_calc_rule_states(int cRules[], int subCount, int sIndex) { int ruleVal=0; int iopStart=sIndex; From 2e973e674292c0e5fa4b0f54548bcbdfab26adb1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 14:24:35 +0100 Subject: [PATCH 0475/1232] m4/nut_report_feature.m4: fix NUT_REPORT_TARGET() for multi-token values of CC_VERSION etc. --- m4/nut_report_feature.m4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index c324f20e4e..dd2666cd58 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -114,7 +114,10 @@ AC_DEFUN([NUT_REPORT_TARGET], dnl arg#3 = summary/config.log/autoconf description AC_MSG_CHECKING([$3]) AC_MSG_RESULT([$2]) - NUT_REPORT_FILE([$3], [$2], [8], "NUT Build/Target system info:") + dnl FIXME: value here is already quoted by caller (for AC_DEFINE_UNQUOTED + dnl with multi-token strings). Then quotes are added in NUT_REPORT_FILE() + dnl and turn it into multiple single-token strings. So we neuter that here: + NUT_REPORT_FILE([$3], ["$2"], [8], "NUT Build/Target system info:") dnl Note: unlike features, target info does not imply an AutoMake toggle AC_DEFINE_UNQUOTED($1, $2, $3) From 7069237795931851817a2f3fed768492884f508b Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 22 Feb 2023 15:25:02 +0200 Subject: [PATCH 0476/1232] .h updates --- drivers/gpio.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpio.h b/drivers/gpio.h index c80a087b82..baf6c773f7 100644 --- a/drivers/gpio.h +++ b/drivers/gpio.h @@ -7,9 +7,9 @@ #include #define DRIVER_NAME "GPIO UPS driver" -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "1.00" -/* rules command definition */ +/* rules commands definition */ #define RULES_CMD_NOT -2 #define RULES_CMD_AND -3 #define RULES_CMD_OR -4 @@ -21,28 +21,28 @@ #define ROPT_REQRES 0x00000001 /* reserve GPIO lines only during request processing */ #define ROPT_EVMODE 0x00000002 /* event driven run */ -typedef struct rulesint_t { - char stateName[12]; - int archVal; - int currVal; - int subCount; - int cRules[]; +typedef struct rulesint_t { /* structure to store processed rules configuration per each state */ + char stateName[12]; /* NUT state name for rules in cRules */ + int archVal; /* previous state value */ + int currVal; /* current state value */ + int subCount; /* element count in translated rules subitem */ + int cRules[]; /* translated rules subitem - rules commands followed by line number(s) */ } rulesint; typedef struct gpioups_t { - struct gpiod_chip *gpioChipHandle; - struct gpiod_line_bulk gpioLines; - struct gpiod_line_bulk gpioEventLines; - int initial; - int runOptions; - int aInfoAvailable; - int chipLinesCount; - int upsLinesCount; - int *upsLines; - int *upsLinesStates; - int upsMaxLine; - int rulesCount; + struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ + struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ + struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ + int initial; /* initialization flag - 0 on 1st entry */ + int runOptions; /* run options, not yet used */ + int aInfoAvailable; /* non-zero if previous state information is available */ + int chipLinesCount; /* gpio chip lines count, set after sucessful open */ + int upsLinesCount; /* no of lines used in rules */ + int *upsLines; /* lines numbers */ + int *upsLinesStates; /* lines states */ + int upsMaxLine; /* maximum line number referenced in rules */ + int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ struct rulesint_t **rules; } gpioups; -#endif /* GPIO_H */ \ No newline at end of file +#endif /* GPIO_H */ From 55a5dca9f4ad3dba980c029350cd460cac561963 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 14:31:24 +0100 Subject: [PATCH 0477/1232] common/common.c: nut_report_config_flags(): make it clear (and safe for in-place mode) when no CONFIG_FLAGS were customized for a NUT build --- common/common.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/common.c b/common/common.c index 55bad80708..bb19c6ef4a 100644 --- a/common/common.c +++ b/common/common.c @@ -968,7 +968,7 @@ void nut_report_config_flags(void) } if (xbit_test(upslog_flags, UPSLOG_STDERR)) - fprintf(stderr, "Network UPS Tools version %s%s%s%s%s%s%s configured with flags: %s\n", + fprintf(stderr, "Network UPS Tools version %s%s%s%s%s%s%s %s%s\n", UPS_VERSION, (relver ? " (release/snapshot of " : ""), (relver ? relver : ""), @@ -976,12 +976,14 @@ void nut_report_config_flags(void) (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), - CONFIG_FLAGS); + (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? "configured with flags: " : "configured all by default guesswork"), + (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? CONFIG_FLAGS : "") + ); /* NOTE: May be ignored or truncated by receiver if that syslog server * (and/or OS sender) does not accept messages of such length */ if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) - syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s%s%s%s configured with flags: %s", + syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s%s%s%s %s%s", UPS_VERSION, (relver ? " (release/snapshot of " : ""), (relver ? relver : ""), @@ -989,7 +991,9 @@ void nut_report_config_flags(void) (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), - CONFIG_FLAGS); + (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? "configured with flags: " : "configured all by default guesswork"), + (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? CONFIG_FLAGS : "") + ); } static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) From 17322b6fdf21e13e33c9c12c8d9569cacc668f11 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 22 Feb 2023 14:43:00 +0100 Subject: [PATCH 0478/1232] common/common.c: nut_report_config_flags(): avoid warnings about unreachable code --- common/common.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/common/common.c b/common/common.c index bb19c6ef4a..4054cf10f5 100644 --- a/common/common.c +++ b/common/common.c @@ -944,7 +944,11 @@ void nut_report_config_flags(void) * Depending on amount of configuration tunables involved by a particular * build of NUT, the string can be quite long (over 1KB). */ - char *relver = NULL; + const char *acinit_ver = NULL; + /* Pass these as variables to avoid warning about never reaching one + * of compiled codepaths: */ + const char *compiler_ver = CC_VERSION; + const char *config_flags = CONFIG_FLAGS; if (nut_debug_level < 1) return; @@ -964,20 +968,20 @@ void nut_report_config_flags(void) * from configure.ac AC_INIT() -- although some distros, * especially embedders, tend to place their product IDs here), * or if PACKAGE_VERSION *is NOT* a substring of it: */ - relver = PACKAGE_VERSION; + acinit_ver = PACKAGE_VERSION; } if (xbit_test(upslog_flags, UPSLOG_STDERR)) fprintf(stderr, "Network UPS Tools version %s%s%s%s%s%s%s %s%s\n", UPS_VERSION, - (relver ? " (release/snapshot of " : ""), - (relver ? relver : ""), - (relver ? ")" : ""), - (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), - (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), - (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), - (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? "configured with flags: " : "configured all by default guesswork"), - (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? CONFIG_FLAGS : "") + (acinit_ver ? " (release/snapshot of " : ""), + (acinit_ver ? acinit_ver : ""), + (acinit_ver ? ")" : ""), + (compiler_ver && *compiler_ver != '\0' ? " built with " : ""), + (compiler_ver && *compiler_ver != '\0' ? compiler_ver : ""), + (compiler_ver && *compiler_ver != '\0' ? " and" : ""), + (config_flags && *config_flags != '\0' ? "configured with flags: " : "configured all by default guesswork"), + (config_flags && *config_flags != '\0' ? config_flags : "") ); /* NOTE: May be ignored or truncated by receiver if that syslog server @@ -985,14 +989,14 @@ void nut_report_config_flags(void) if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s%s%s%s %s%s", UPS_VERSION, - (relver ? " (release/snapshot of " : ""), - (relver ? relver : ""), - (relver ? ")" : ""), - (CC_VERSION && *CC_VERSION != '\0' ? " built with " : ""), - (CC_VERSION && *CC_VERSION != '\0' ? CC_VERSION : ""), - (CC_VERSION && *CC_VERSION != '\0' ? " and" : ""), - (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? "configured with flags: " : "configured all by default guesswork"), - (CONFIG_FLAGS && *CONFIG_FLAGS != '\0' ? CONFIG_FLAGS : "") + (acinit_ver ? " (release/snapshot of " : ""), + (acinit_ver ? acinit_ver : ""), + (acinit_ver ? ")" : ""), + (compiler_ver && *compiler_ver != '\0' ? " built with " : ""), + (compiler_ver && *compiler_ver != '\0' ? compiler_ver : ""), + (compiler_ver && *compiler_ver != '\0' ? " and" : ""), + (config_flags && *config_flags != '\0' ? "configured with flags: " : "configured all by default guesswork"), + (config_flags && *config_flags != '\0' ? config_flags : "") ); } From 545ace32ee14254e5ed7cf439254ad5ef7813bdf Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 22 Feb 2023 17:26:30 +0200 Subject: [PATCH 0479/1232] PR preparation fixes --- docs/man/Makefile.am | 20 +++++++++++++++++--- docs/man/gpio.txt | 6 +++--- drivers/gpio.c | 8 ++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 53ab88017e..ba545f9695 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -669,6 +669,17 @@ endif HTML_LINUX_I2C_MANS = asem.html pijuice.html +SRC_LINUX_GPIO_PAGES = gpio.txt +if WITH_MANS +MAN_LINUX_GPIO_PAGES = gpio.8 +endif + +if WITH_GPIO +man8_MANS += $(MAN_LINUX_GPIO_PAGES) +endif + +HTML_LINUX_GPIO_MANS = gpio.html + # SOME_DRIVERS endif @@ -691,7 +702,8 @@ MAN_MANS += \ $(MAN_IPMIPSU_PAGES) \ $(MAN_MACOSX_PAGES) \ $(MAN_MODBUS_PAGES) \ - $(MAN_LINUX_I2C_PAGES) + $(MAN_LINUX_I2C_PAGES) \ + $(MAN_LINUX_GPIO_PAGES) endif SRC_DRIVERS_PAGES = \ @@ -704,7 +716,8 @@ SRC_DRIVERS_PAGES = \ $(SRC_IPMIPSU_PAGES) \ $(SRC_MACOSX_PAGES) \ $(SRC_MODBUS_PAGES) \ - $(SRC_LINUX_I2C_PAGES) + $(SRC_LINUX_I2C_PAGES) \ + $(SRC_LINUX_GPIO_PAGES) if SOME_DRIVERS # The list above probably came up empty in this case, so make sure that @@ -762,7 +775,8 @@ HTML_MANS = \ $(HTML_IPMIPSU_MANS) \ $(HTML_MACOSX_MANS) \ $(HTML_MODBUS_MANS) \ - $(HTML_LINUX_I2C_MANS) + $(HTML_LINUX_I2C_MANS) \ + $(HTML_LINUX_GPIO_MANS) # Note: target documents, except nutupsdrv.txt itself, start the # list of drivers with `- linkman:nutupsdrv[8]` entry diff --git a/docs/man/gpio.txt b/docs/man/gpio.txt index be16215300..ebeac2d667 100644 --- a/docs/man/gpio.txt +++ b/docs/man/gpio.txt @@ -38,9 +38,9 @@ Driver control: ~~~~~~~~~~~~~~ *rules*='value':: -A string consisting of substrings. Each substring describes GPIO line +A string consisting of sub-strings. Each sub-string describes GPIO line states conversion formula to specific NUT state, like -nut_state=[^]line_num[logical_operationline_num]. Not (^) , and (&) , or +nut_state=[^]line_num[logical_operation.line_num]. Not (^) , and (&) , or (|)operations are supported for now. nut_state should correspond to NUT state, line_num to GPIO line number connected to UPS open collector pin. CyberShield CSN27U12V describes pins as: @@ -81,7 +81,7 @@ Here is an example of GPIO driver configuration in *ups.conf* file: default.battery.charge.low = 20 ---- -SHTDOWN COMMAND +SHUTDOWN COMMAND --------------- This driver does not support shutdown command. diff --git a/drivers/gpio.c b/drivers/gpio.c index 9ecdebd2ae..bf63906e70 100644 --- a/drivers/gpio.c +++ b/drivers/gpio.c @@ -67,7 +67,7 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd); static void gpio_get_lines_states(struct gpioups_t *gpioupsfd); static void gpio_set_states(struct gpioups_t *gpioupsfd); -#undef LOCALTEST +#define LOCALTEST #ifdef LOCALTEST struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { NUT_UNUSED_VARIABLE(name); @@ -217,9 +217,6 @@ static void gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd->rules) { int i; for(i=0; irulesCount; i++) { - if(gpioupsfd->rules[i].cRules) { - free(gpioupsfd->rules[i].cRules); - } free(gpioupsfd->rules[i]); } } @@ -354,8 +351,7 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { for(i=0; irulesCount; i++) { upsdebugx( LOG_DEBUG, - "rule state name [%s], - subcount %d", + "rule state name [%s], subcount %d", upsfd->rules[i]->stateName, upsfd->rules[i]->subCount ); From 7b8d5090d8df4c6661767661ab5dfe0287f3a80a Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 22 Feb 2023 18:47:42 +0200 Subject: [PATCH 0480/1232] removed local test define --- drivers/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio.c b/drivers/gpio.c index bf63906e70..cc94471b09 100644 --- a/drivers/gpio.c +++ b/drivers/gpio.c @@ -67,7 +67,7 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd); static void gpio_get_lines_states(struct gpioups_t *gpioupsfd); static void gpio_set_states(struct gpioups_t *gpioupsfd); -#define LOCALTEST +#undef LOCALTEST #ifdef LOCALTEST struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { NUT_UNUSED_VARIABLE(name); From 3b6c8450b089db9416ee7c42ddcb7fbb0f475e02 Mon Sep 17 00:00:00 2001 From: modrisb Date: Thu, 23 Feb 2023 11:44:29 +0200 Subject: [PATCH 0481/1232] man page spellcheck fixes --- docs/man/gpio.txt | 4 ++-- docs/nut.dict | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/man/gpio.txt b/docs/man/gpio.txt index ebeac2d667..cbec3c4e5a 100644 --- a/docs/man/gpio.txt +++ b/docs/man/gpio.txt @@ -52,7 +52,7 @@ BATTERY MISSING Low when battery is present Open when battery is missing LOW BATTERY Low when battery is near full charge capacity Open when operating from a battery with < 20% capacity -and rules migh be defined as +and rules might be defined as rules = "OL=^0;OB=0;LB=3;RB=1;DISCHRG=0&^6;BYPASS=6;" assuming that line 0 is connected to ON BATTERY pin, REPLACE BATTERY to line 1, BATTERY MISSING pin to line 6 and LOW BATTERY to line 3. Expecting simple formula @@ -82,7 +82,7 @@ Here is an example of GPIO driver configuration in *ups.conf* file: ---- SHUTDOWN COMMAND ---------------- +---------------- This driver does not support shutdown command. diff --git a/docs/nut.dict b/docs/nut.dict index bbc8bdc5df..df101b25c1 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3095 utf-8 +personal_ws-1.1 en 3105 utf-8 AAS ABI ACFAIL @@ -131,6 +131,7 @@ BeepTone Belkin's Benedikt Berge +Berzonis BestPort BiWeekly Bieringer @@ -192,6 +193,7 @@ CPUs CRC CREAD CROSSTALK +CSN CSS CSUM CTB @@ -230,6 +232,7 @@ Ctrl Cuvellard Cyber CyberPower +CyberShield Cygwin DATACABLE DATAPATH @@ -255,6 +258,7 @@ DIGYS DISCHRG DMF DN +DNS DOCTYPE DOMAINs DPC @@ -389,6 +393,8 @@ GETADDRINFO GID GKrellM GND +GPIO +GPIOCHIP GPL GPSER GRs @@ -699,6 +705,7 @@ Minislot Moar Modbus ModemManager +Modris MonAMI MonUPS Monett @@ -1949,6 +1956,8 @@ google goto gotos gpg +gpio +gpiochip graphviz groupadd groupname @@ -2131,6 +2140,7 @@ libexec libfreeipmi libgd libgpgme +libgpiod libhid libhidups libi From e8a4dbe65ae137bc62eafbc2c0a5cbc4308b10fd Mon Sep 17 00:00:00 2001 From: modrisb Date: Thu, 23 Feb 2023 23:02:45 +0200 Subject: [PATCH 0482/1232] refactored to better split generic code from gpio library specific code --- drivers/gpio.c | 117 ++++++++++++++++++++++++++++++------------------- drivers/gpio.h | 11 +++-- 2 files changed, 79 insertions(+), 49 deletions(-) diff --git a/drivers/gpio.c b/drivers/gpio.c index cc94471b09..55e8a3ec8a 100644 --- a/drivers/gpio.c +++ b/drivers/gpio.c @@ -61,13 +61,13 @@ upsdrv_info_t upsdrv_info = { struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; static struct gpioups_t *gpio_open(const char *chipName); -static void reserve_lines(struct gpioups_t *gpioupsfd, int inner); +static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); static void gpio_close(struct gpioups_t *upsfd); static void gpio_get_ups_rules(struct gpioups_t *upsfd); -static void gpio_get_lines_states(struct gpioups_t *gpioupsfd); +static void gpio_get_lines_states_libgpiod(struct gpioups_t *gpioupsfd); static void gpio_set_states(struct gpioups_t *gpioupsfd); -#undef LOCALTEST +#define LOCALTEST #ifdef LOCALTEST struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { NUT_UNUSED_VARIABLE(name); @@ -128,21 +128,22 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, /* reserve GPIO lines as per run options and inner parameter: do reservation once or per each status read */ -static void reserve_lines(struct gpioups_t *gpioupsfd, int inner) { - upsdebugx(LOG_DEBUG, "reserve_lines runOptions %d, inner %d", gpioupsfd->runOptions, inner); +static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions %d, inner %d", gpioupsfd->runOptions, inner); if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { struct gpiod_line_request_config config; int gpioRc; config.consumer=upsdrv_info.name; if(gpioupsfd->runOptions&ROPT_EVMODE) { config.request_type=GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; - upsdebugx(LOG_DEBUG, "reserve_lines GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); } else { config.request_type=GPIOD_LINE_REQUEST_DIRECTION_INPUT; - upsdebugx(LOG_DEBUG, "reserve_lines GPIOD_LINE_REQUEST_DIRECTION_INPUT"); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_DIRECTION_INPUT"); } config.flags=0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ - gpioRc=gpiod_line_request_bulk(&gpioupsfd->gpioLines, &config, NULL); + gpioRc=gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL); if(gpioRc) fatal_with_errno( LOG_ERR, @@ -158,37 +159,36 @@ static void reserve_lines(struct gpioups_t *gpioupsfd, int inner) { } /* open gpiochip, process rules and check lines numbers validity */ -static struct gpioups_t *gpio_open(const char *chipName) { - struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); - upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ - gpio_get_ups_rules(upsfdlocal); - upsfdlocal->gpioChipHandle=gpiod_chip_open_by_name(chipName); - if(!upsfdlocal->gpioChipHandle) { +static void gpio_open_libgpiod(struct gpioups_t *gpioupsfd) { + struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); + gpioupsfd->lib_data=libgpiod_data; + libgpiod_data->gpioChipHandle=gpiod_chip_open_by_name(gpioupsfd->chipName); + if(!libgpiod_data->gpioChipHandle) { fatal_with_errno( LOG_ERR, "Could not open GPIO chip [%s], check chips presence and/or access rights", - chipName + gpioupsfd->chipName ); } else { int gpioRc; - upslogx(LOG_NOTICE, "GPIO chip [%s] opened", chipName); - upsfdlocal->chipLinesCount=gpiod_chip_num_lines(upsfdlocal->gpioChipHandle); - upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", upsfdlocal->chipLinesCount, chipName); - if(upsfdlocal->chipLinesCountupsMaxLine) + upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); + gpioupsfd->chipLinesCount=gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); + upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); + if(gpioupsfd->chipLinesCountupsMaxLine) fatalx( LOG_ERR, "GPIO chip lines count %d smaller than UPS line number used (%d)", - upsfdlocal->chipLinesCount, - upsfdlocal->upsMaxLine + gpioupsfd->chipLinesCount, + gpioupsfd->upsMaxLine ); - upsfdlocal->upsLinesStates=xcalloc(sizeof(int), upsfdlocal->upsLinesCount); - gpiod_line_bulk_init(&upsfdlocal->gpioLines); - gpiod_line_bulk_init(&upsfdlocal->gpioEventLines); + gpioupsfd->upsLinesStates=xcalloc(sizeof(int), gpioupsfd->upsLinesCount); + gpiod_line_bulk_init(&libgpiod_data->gpioLines); + gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); gpioRc=gpiod_chip_get_lines( - upsfdlocal->gpioChipHandle, - (unsigned int *)upsfdlocal->upsLines, - upsfdlocal->upsLinesCount, - &upsfdlocal->gpioLines + libgpiod_data->gpioChipHandle, + (unsigned int *)gpioupsfd->upsLines, + gpioupsfd->upsLinesCount, + &libgpiod_data->gpioLines ); if(gpioRc) fatal_with_errno( @@ -197,17 +197,35 @@ static struct gpioups_t *gpio_open(const char *chipName) { gpioRc ); upsdebugx(LOG_DEBUG, "GPIO gpiod_chip_get_lines return code %d", gpioRc); - reserve_lines(upsfdlocal, 0); + reserve_lines_libgpiod(gpioupsfd, 0); } +} + +/* open gpiochip, process rules and check lines numbers validity */ +static struct gpioups_t *gpio_open(const char *chipName) { + struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); + upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ + upsfdlocal->chipName=chipName; + gpio_get_ups_rules(upsfdlocal); return upsfdlocal; } +static void gpio_close_libgpiod(struct gpioups_t *gpioupsfd) { + if(gpioupsfd) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + if(libgpiod_data) { + if(libgpiod_data->gpioChipHandle) { + gpiod_chip_close(libgpiod_data->gpioChipHandle); + } + free(gpioupsfd->lib_data); + gpioupsfd->lib_data = NULL; + } + } +} + /* close gpiochip and release any allocated resources */ static void gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd) { - if(gpioupsfd->gpioChipHandle) { - gpiod_chip_close(gpioupsfd->gpioChipHandle); - } if(gpioupsfd->upsLines) { free(gpioupsfd->upsLines); } @@ -431,17 +449,18 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { } /* get GPIO line states for all needed lines */ -static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { +static void gpio_get_lines_states_libgpiod(struct gpioups_t *gpioupsfd) { int i; int gpioRc; - reserve_lines(gpioupsfd, 1); + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + reserve_lines_libgpiod(gpioupsfd, 1); if(gpioupsfd->runOptions&ROPT_EVMODE) { struct timespec timeoutLong={1,0}; struct gpiod_line_event event; int monRes; upsdebugx( LOG_DEBUG, - "gpio_get_lines_states initial %d, timeout %ld", + "gpio_get_lines_states_libgpiod initial %d, timeout %ld", gpioupsfd->initial, timeoutLong.tv_sec ); @@ -452,15 +471,15 @@ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { } upsdebugx( LOG_DEBUG, - "gpio_get_lines_states initial %d, timeout %ld", + "gpio_get_lines_states_libgpiod initial %d, timeout %ld", gpioupsfd->initial, timeoutLong.tv_sec ); - gpiod_line_bulk_init(&gpioupsfd->gpioEventLines); + gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); monRes=gpiod_line_event_wait_bulk( - &gpioupsfd->gpioLines, + &libgpiod_data->gpioLines, &timeoutLong, - &gpioupsfd->gpioEventLines + &libgpiod_data->gpioEventLines ); upsdebugx( LOG_DEBUG, @@ -469,11 +488,11 @@ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { timeoutLong.tv_sec ); if(monRes==1) { - int num_lines=(int)gpiod_line_bulk_num_lines(&gpioupsfd->gpioEventLines); + int num_lines=(int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); int i; for(i=0; igpioEventLines, + &libgpiod_data->gpioEventLines, i ); int eventRc=gpiod_line_event_read(eLine, &event); @@ -493,7 +512,7 @@ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { gpioupsfd->upsLinesStates[i]=-1; } gpioRc=gpiod_line_get_value_bulk( - &gpioupsfd->gpioLines, + &libgpiod_data->gpioLines, gpioupsfd->upsLinesStates ); if (gpioRc<0) @@ -512,7 +531,7 @@ static void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { ); } if(gpioupsfd->runOptions&ROPT_REQRES) { - gpiod_line_release_bulk(&gpioupsfd->gpioLines); + gpiod_line_release_bulk(&libgpiod_data->gpioLines); } } @@ -623,7 +642,7 @@ void upsdrv_initinfo(void) void upsdrv_updateinfo(void) { /* read GPIO lines states */ - gpio_get_lines_states(gpioupsfd); + gpio_get_lines_states_libgpiod(gpioupsfd); /* calculate/set UPS states based on line values */ gpio_set_states(gpioupsfd); @@ -656,12 +675,18 @@ void upsdrv_makevartable(void) void upsdrv_initups(void) { - /* open GPIO chip and check pin consistence */ + /* prepare rules and allocate related structures */ gpioupsfd=gpio_open(device_path); + /* open GPIO chip and check pin consistence */ + if(gpioupsfd) { + gpio_open_libgpiod(gpioupsfd); + } } void upsdrv_cleanup(void) { - /* close GPIO chip and release related resources */ + /* release gpio library resources */ + gpio_close_libgpiod(gpioupsfd); + /* release related generic resources */ gpio_close(gpioupsfd); } \ No newline at end of file diff --git a/drivers/gpio.h b/drivers/gpio.h index baf6c773f7..70be8af2c9 100644 --- a/drivers/gpio.h +++ b/drivers/gpio.h @@ -30,9 +30,8 @@ typedef struct rulesint_t { /* structure to store processed rules configuration } rulesint; typedef struct gpioups_t { - struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ - struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ - struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ + void *lib_data; /* pointer to driver's gpio support library data structure */ + const char *chipName; /* port or file name to reference GPIO chip */ int initial; /* initialization flag - 0 on 1st entry */ int runOptions; /* run options, not yet used */ int aInfoAvailable; /* non-zero if previous state information is available */ @@ -45,4 +44,10 @@ typedef struct gpioups_t { struct rulesint_t **rules; } gpioups; +typedef struct libgpiod_data_t { + struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ + struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ + struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ +} libgpiod_data; + #endif /* GPIO_H */ From 8e220ca8abd6d1195215ea8caf29cb743a9392db Mon Sep 17 00:00:00 2001 From: modrisb Date: Sat, 25 Feb 2023 19:13:55 +0200 Subject: [PATCH 0483/1232] renamed source code files --- docs/man/gpio.txt | 12 +- drivers/Makefile.am | 10 +- drivers/{gpio.c => generic_gpio_common.c} | 280 ++------------------ drivers/{gpio.h => generic_gpio_common.h} | 17 +- drivers/generic_gpio_libgpiod.c | 296 ++++++++++++++++++++++ drivers/generic_gpio_libgpiod.h | 15 ++ 6 files changed, 345 insertions(+), 285 deletions(-) rename drivers/{gpio.c => generic_gpio_common.c} (61%) rename drivers/{gpio.h => generic_gpio_common.h} (81%) create mode 100644 drivers/generic_gpio_libgpiod.c create mode 100644 drivers/generic_gpio_libgpiod.h diff --git a/docs/man/gpio.txt b/docs/man/gpio.txt index cbec3c4e5a..289d4d0246 100644 --- a/docs/man/gpio.txt +++ b/docs/man/gpio.txt @@ -1,17 +1,17 @@ -GPIO(8) +GENERIC GPIO(8) ================= NAME ---- -GPIO - Driver for GPIO connected UPS +GENERIC GPIO - Driver for GPIO connected UPS SYNOPSIS -------- -*GPIO* -h +*GENERIC_GPIO* -h -*GPIO* -a 'GPIOCHIP0' ['OPTIONS'] +*GENERIC_GPIO* -a 'GPIOCHIP0' ['OPTIONS'] NOTE: This man page only documents the specific features of the *GPIO* driver. For information about the core driver, see linkman:nutupsdrv[8]. @@ -21,7 +21,7 @@ SUPPORTED HARDWARE This is the driver for GPIO attached UPS devices. -The driver has been tested against CyberPower CyberShield CSN27U12V attached +The driver has been tested against CyberPower CyberShield CSN27U12V attached to Orange Pi Zero GPIO. More information about this UPS can be found here: :: @@ -72,7 +72,7 @@ CONFIGURATION Here is an example of GPIO driver configuration in *ups.conf* file: ---- [CyberPower12v] - driver = GPIO + driver = GENERIC_GPIO port = gpiochip0 description = "Modem and DNS server UPS" mfr = CyberPower diff --git a/drivers/Makefile.am b/drivers/Makefile.am index c9c7daf28c..c0692cd84a 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -59,7 +59,7 @@ MODBUS_DRIVERLIST = phoenixcontact_modbus generic_modbus huawei-ups2000 socomec_ LINUX_I2C_DRIVERLIST = asem pijuice POWERMAN_DRIVERLIST = powerman-pdu IPMI_DRIVERLIST = nut-ipmipsu -GPIO_DRIVERLIST = gpio +GPIO_DRIVERLIST = generic_gpio_libgpiod # distribute all drivers, even ones that are not built by default EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) @@ -171,9 +171,11 @@ upscode2_LDADD = $(LDADD) -lm victronups_SOURCES = victronups.c riello_ser_SOURCES = riello.c riello_ser.c riello_ser_LDADD = $(LDADD) -lm -gpio_SOURCES = gpio.c -gpio_CFLAGS = $(AM_CFLAGS) -gpio_LDADD = $(LDADD_DRIVERS) -lgpiod +#gpio_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c +generic_gpio_libgpiod_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c +#gpio_CFLAGS = $(AM_CFLAGS) +#gpio_LDADD = $(LDADD_DRIVERS) -lgpiod +generic_gpio_libgpiod_LDADD = $(LDADD_DRIVERS) -lgpiod # non-serial drivers: these use custom LDADD and/or CFLAGS diff --git a/drivers/gpio.c b/drivers/generic_gpio_common.c similarity index 61% rename from drivers/gpio.c rename to drivers/generic_gpio_common.c index 55e8a3ec8a..b55a86d4ee 100644 --- a/drivers/gpio.c +++ b/drivers/generic_gpio_common.c @@ -17,16 +17,7 @@ #include "config.h" #include "main.h" #include "attribute.h" -#include "gpio.h" - -/* driver description structure */ -upsdrv_info_t upsdrv_info = { - DRIVER_NAME, - DRIVER_VERSION, - "ModrisB ", - DRV_STABLE, - { NULL } -}; +#include "generic_gpio_common.h" /* CyberPower 12V open collector state definitions 0 ON BATTERY Low when operating from utility line @@ -60,171 +51,19 @@ upsdrv_info_t upsdrv_info = { struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; -static struct gpioups_t *gpio_open(const char *chipName); -static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); -static void gpio_close(struct gpioups_t *upsfd); -static void gpio_get_ups_rules(struct gpioups_t *upsfd); -static void gpio_get_lines_states_libgpiod(struct gpioups_t *gpioupsfd); -static void gpio_set_states(struct gpioups_t *gpioupsfd); - -#define LOCALTEST -#ifdef LOCALTEST -struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { - NUT_UNUSED_VARIABLE(name); - return (struct gpiod_chip *)1; -} - -unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { - NUT_UNUSED_VARIABLE(chip); - return 32; -} -int gpiod_chip_get_lines(struct gpiod_chip *chip, - unsigned int *offsets, unsigned int num_offsets, - struct gpiod_line_bulk *bulk) { - return 0; -} - -int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, - const struct gpiod_line_request_config *config, - const int *default_vals) -{ - return 0; -} - -int gStatus = 0; - -int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, - int *values) -{ - int pinPos=1; - if(gpioupsfd) - for(int i=0; iupsLinesCount; i++) { - values[i]=(gStatus&pinPos)!=0; - pinPos=pinPos<<1; - } - - gStatus++; - return 0; -} - -int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, - const struct timespec *timeout, - struct gpiod_line_bulk *event_bulk) -{ - switch(gStatus%3) { - case 0: - sleep(2); - break; - case 1: - sleep(4); - break; - case 2: - sleep(6); - break; - } - return 0; -} -#endif - -/* reserve GPIO lines as per run options and inner parameter: do reservation once - or per each status read */ -static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions %d, inner %d", gpioupsfd->runOptions, inner); - if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { - struct gpiod_line_request_config config; - int gpioRc; - config.consumer=upsdrv_info.name; - if(gpioupsfd->runOptions&ROPT_EVMODE) { - config.request_type=GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); - } else { - config.request_type=GPIOD_LINE_REQUEST_DIRECTION_INPUT; - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_DIRECTION_INPUT"); - } - config.flags=0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ - gpioRc=gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL); - if(gpioRc) - fatal_with_errno( - LOG_ERR, - "GPIO gpiod_line_request_bulk call failed, check for other applications that may have reserved GPIO lines" - ); - upsdebugx( - LOG_DEBUG, - "GPIO gpiod_line_request_bulk with type %d return code %d", - config.request_type, - gpioRc - ); - } -} +static void get_ups_rules(struct gpioups_t *upsfd); /* open gpiochip, process rules and check lines numbers validity */ -static void gpio_open_libgpiod(struct gpioups_t *gpioupsfd) { - struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); - gpioupsfd->lib_data=libgpiod_data; - libgpiod_data->gpioChipHandle=gpiod_chip_open_by_name(gpioupsfd->chipName); - if(!libgpiod_data->gpioChipHandle) { - fatal_with_errno( - LOG_ERR, - "Could not open GPIO chip [%s], check chips presence and/or access rights", - gpioupsfd->chipName - ); - } else { - int gpioRc; - upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); - gpioupsfd->chipLinesCount=gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); - upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); - if(gpioupsfd->chipLinesCountupsMaxLine) - fatalx( - LOG_ERR, - "GPIO chip lines count %d smaller than UPS line number used (%d)", - gpioupsfd->chipLinesCount, - gpioupsfd->upsMaxLine - ); - gpioupsfd->upsLinesStates=xcalloc(sizeof(int), gpioupsfd->upsLinesCount); - gpiod_line_bulk_init(&libgpiod_data->gpioLines); - gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); - gpioRc=gpiod_chip_get_lines( - libgpiod_data->gpioChipHandle, - (unsigned int *)gpioupsfd->upsLines, - gpioupsfd->upsLinesCount, - &libgpiod_data->gpioLines - ); - if(gpioRc) - fatal_with_errno( - LOG_ERR, - "GPIO line reservation (gpiod_chip_get_lines call) failed with code %d, check for possible issue in rules parameter", - gpioRc - ); - upsdebugx(LOG_DEBUG, "GPIO gpiod_chip_get_lines return code %d", gpioRc); - reserve_lines_libgpiod(gpioupsfd, 0); - } -} - -/* open gpiochip, process rules and check lines numbers validity */ -static struct gpioups_t *gpio_open(const char *chipName) { +static struct gpioups_t *generic_gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ upsfdlocal->chipName=chipName; - gpio_get_ups_rules(upsfdlocal); + get_ups_rules(upsfdlocal); return upsfdlocal; } -static void gpio_close_libgpiod(struct gpioups_t *gpioupsfd) { - if(gpioupsfd) { - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - if(libgpiod_data) { - if(libgpiod_data->gpioChipHandle) { - gpiod_chip_close(libgpiod_data->gpioChipHandle); - } - free(gpioupsfd->lib_data); - gpioupsfd->lib_data = NULL; - } - } -} - /* close gpiochip and release any allocated resources */ -static void gpio_close(struct gpioups_t *gpioupsfd) { +static void generic_gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd) { if(gpioupsfd->upsLines) { free(gpioupsfd->upsLines); @@ -282,7 +121,7 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { } /* split subrules and translate them to array of commands/line numbers */ -static void gpio_get_ups_rules(struct gpioups_t *upsfd) { +static void get_ups_rules(struct gpioups_t *upsfd) { unsigned char *rulesString=(unsigned char *)getval("rules"); /* statename=[^]line[&||[line]] */ char lexBuff[33]; @@ -448,95 +287,8 @@ static void gpio_get_ups_rules(struct gpioups_t *upsfd) { } } -/* get GPIO line states for all needed lines */ -static void gpio_get_lines_states_libgpiod(struct gpioups_t *gpioupsfd) { - int i; - int gpioRc; - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - reserve_lines_libgpiod(gpioupsfd, 1); - if(gpioupsfd->runOptions&ROPT_EVMODE) { - struct timespec timeoutLong={1,0}; - struct gpiod_line_event event; - int monRes; - upsdebugx( - LOG_DEBUG, - "gpio_get_lines_states_libgpiod initial %d, timeout %ld", - gpioupsfd->initial, - timeoutLong.tv_sec - ); - if(gpioupsfd->initial) { - timeoutLong.tv_sec=35; - } else { - gpioupsfd->initial=1; - } - upsdebugx( - LOG_DEBUG, - "gpio_get_lines_states_libgpiod initial %d, timeout %ld", - gpioupsfd->initial, - timeoutLong.tv_sec - ); - gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); - monRes=gpiod_line_event_wait_bulk( - &libgpiod_data->gpioLines, - &timeoutLong, - &libgpiod_data->gpioEventLines - ); - upsdebugx( - LOG_DEBUG, - "gpiod_line_event_wait_bulk completed with %d return code and timeout %ld s", - monRes, - timeoutLong.tv_sec - ); - if(monRes==1) { - int num_lines=(int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); - int i; - for(i=0; igpioEventLines, - i - ); - int eventRc=gpiod_line_event_read(eLine, &event); - unsigned int lineOffset=gpiod_line_offset(eLine); - event.event_type=0; - upsdebugx( - LOG_DEBUG, - "Event read return code %d and event type %d for line %d", - eventRc, - event.event_type, - lineOffset - ); - } - } - } - for(i=0; iupsLinesCount; i++) { - gpioupsfd->upsLinesStates[i]=-1; - } - gpioRc=gpiod_line_get_value_bulk( - &libgpiod_data->gpioLines, - gpioupsfd->upsLinesStates - ); - if (gpioRc<0) - fatal_with_errno(LOG_ERR, "GPIO line status read call failed"); - upsdebugx( - LOG_DEBUG, - "GPIO gpiod_line_get_value_bulk completed with %d return code, status values:", - gpioRc - ); - for(i=0; iupsLinesCount; i++) { - upsdebugx( - LOG_DEBUG, - "Line%d state = %d", - i, - gpioupsfd->upsLinesStates[i] - ); - } - if(gpioupsfd->runOptions&ROPT_REQRES) { - gpiod_line_release_bulk(&libgpiod_data->gpioLines); - } -} - /* calculate state rule value based on GPIO line values */ -static int gpio_calc_rule_states(int cRules[], int subCount, int sIndex) { +static int calc_rule_states(int cRules[], int subCount, int sIndex) { int ruleVal=0; int iopStart=sIndex; int rs; @@ -550,7 +302,7 @@ static int gpio_calc_rule_states(int cRules[], int subCount, int sIndex) { iopStart++; } if(iopStartrulesCount; ruleNo++) { gpioupsfd->rules[ruleNo]->currVal= - gpio_calc_rule_states( + calc_rule_states( gpioupsfd->rules[ruleNo]->cRules, gpioupsfd->rules[ruleNo]->subCount, 0 ); @@ -642,10 +394,10 @@ void upsdrv_initinfo(void) void upsdrv_updateinfo(void) { /* read GPIO lines states */ - gpio_get_lines_states_libgpiod(gpioupsfd); + gpio_get_lines_states(gpioupsfd); /* calculate/set UPS states based on line values */ - gpio_set_states(gpioupsfd); + update_ups_states(gpioupsfd); /* no protocol failures possible - mark data as OK */ dstate_dataok(); @@ -676,17 +428,17 @@ void upsdrv_makevartable(void) void upsdrv_initups(void) { /* prepare rules and allocate related structures */ - gpioupsfd=gpio_open(device_path); + gpioupsfd=generic_gpio_open(device_path); /* open GPIO chip and check pin consistence */ if(gpioupsfd) { - gpio_open_libgpiod(gpioupsfd); + gpio_open(gpioupsfd); } } void upsdrv_cleanup(void) { /* release gpio library resources */ - gpio_close_libgpiod(gpioupsfd); - /* release related generic resources */ gpio_close(gpioupsfd); + /* release related generic resources */ + generic_gpio_close(gpioupsfd); } \ No newline at end of file diff --git a/drivers/gpio.h b/drivers/generic_gpio_common.h similarity index 81% rename from drivers/gpio.h rename to drivers/generic_gpio_common.h index 70be8af2c9..e25b634e2c 100644 --- a/drivers/gpio.h +++ b/drivers/generic_gpio_common.h @@ -1,14 +1,11 @@ -#ifndef GPIO_H -#define GPIO_H +#ifndef GENERIC_GPIO_COMMON_H +#define GENERIC_GPIO_COMMON_H #include #include #include #include -#define DRIVER_NAME "GPIO UPS driver" -#define DRIVER_VERSION "1.00" - /* rules commands definition */ #define RULES_CMD_NOT -2 #define RULES_CMD_AND -3 @@ -44,10 +41,8 @@ typedef struct gpioups_t { struct rulesint_t **rules; } gpioups; -typedef struct libgpiod_data_t { - struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ - struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ - struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ -} libgpiod_data; +void gpio_open(struct gpioups_t *gpioupsfd); +void gpio_get_lines_states(struct gpioups_t *gpioupsfd); +void gpio_close(struct gpioups_t *gpioupsfd); -#endif /* GPIO_H */ +#endif /* GENERIC_GPIO_COMMON_H */ diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c new file mode 100644 index 0000000000..50f075fdfa --- /dev/null +++ b/drivers/generic_gpio_libgpiod.c @@ -0,0 +1,296 @@ +/* + anything commented is optional + anything else is mandatory + + for more information, refer to: + * docs/developers.txt + * docs/new-drivers.txt + * docs/new-names.txt + + and possibly also to: + * docs/hid-subdrivers.txt for USB/HID devices + * or docs/snmp-subdrivers.txt for SNMP devices +*/ +/* ./configure --with-pidpath=/run/nut --with-altpidpath=/run/nut --with-statepath=/run/nut --sysconfdir=/etc/nut --with-gpio --with-user=nut --with-group=nut */ +#pragma GCC optimize("O0") + +#include "config.h" +#include "main.h" +#include "attribute.h" +#include "generic_gpio_common.h" +#include "generic_gpio_libgpiod.h" + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "ModrisB ", + DRV_STABLE, + { NULL } +}; + +static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); + +/* CyberPower 12V open collector state definitions + 0 ON BATTERY Low when operating from utility line + Open when operating from battery + 1 REPLACE BATTERY Low when battery is charged + Open when battery fails the Self Test + 6 BATTERY MISSING Low when battery is present + Open when battery is missing + 3 LOW BATTERY Low when battery is near full charge capacity + Open when operating from a battery with < 20% capacity + + NUT supported states + OL On line (mains is present) + OB On battery (mains is not present) + LB Low battery + HB High battery + RB The battery needs to be replaced + CHRG The battery is charging + DISCHRG The battery is discharging (inverter is providing load power) + BYPASS UPS bypass circuit is active -- no battery protection is available + CAL UPS is currently performing runtime calibration (on battery) + OFF UPS is offline and is not supplying power to the load + OVER UPS is overloaded + TRIM UPS is trimming incoming voltage (called "buck" in some hardware) + BOOST UPS is boosting incoming voltage + FSD Forced Shutdown (restricted use, see the note below) + + CyberPower rules setting + OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; +*/ + +#define LOCALTEST +#ifdef LOCALTEST +struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { + NUT_UNUSED_VARIABLE(name); + return (struct gpiod_chip *)1; +} + +unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { + NUT_UNUSED_VARIABLE(chip); + return 32; +} +int gpiod_chip_get_lines(struct gpiod_chip *chip, + unsigned int *offsets, unsigned int num_offsets, + struct gpiod_line_bulk *bulk) { + return 0; +} + +int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, + const struct gpiod_line_request_config *config, + const int *default_vals) +{ + return 0; +} + +int gStatus = 0; + +int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, + int *values) +{ + int pinPos=1; + if(gpioupsfd) + for(int i=0; iupsLinesCount; i++) { + values[i]=(gStatus&pinPos)!=0; + pinPos=pinPos<<1; + } + + gStatus++; + return 0; +} + +int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, + const struct timespec *timeout, + struct gpiod_line_bulk *event_bulk) +{ + switch(gStatus%3) { + case 0: + sleep(2); + break; + case 1: + sleep(4); + break; + case 2: + sleep(6); + break; + } + return 0; +} +#endif + +/* reserve GPIO lines as per run options and inner parameter: do reservation once + or per each status read */ +static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions %d, inner %d", gpioupsfd->runOptions, inner); + if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { + struct gpiod_line_request_config config; + int gpioRc; + config.consumer=upsdrv_info.name; + if(gpioupsfd->runOptions&ROPT_EVMODE) { + config.request_type=GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); + } else { + config.request_type=GPIOD_LINE_REQUEST_DIRECTION_INPUT; + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_DIRECTION_INPUT"); + } + config.flags=0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ + gpioRc=gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL); + if(gpioRc) + fatal_with_errno( + LOG_ERR, + "GPIO gpiod_line_request_bulk call failed, check for other applications that may have reserved GPIO lines" + ); + upsdebugx( + LOG_DEBUG, + "GPIO gpiod_line_request_bulk with type %d return code %d", + config.request_type, + gpioRc + ); + } +} + +/* open gpiochip, process rules and check lines numbers validity */ +void gpio_open(struct gpioups_t *gpioupsfd) { + struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); + gpioupsfd->lib_data=libgpiod_data; + libgpiod_data->gpioChipHandle=gpiod_chip_open_by_name(gpioupsfd->chipName); + if(!libgpiod_data->gpioChipHandle) { + fatal_with_errno( + LOG_ERR, + "Could not open GPIO chip [%s], check chips presence and/or access rights", + gpioupsfd->chipName + ); + } else { + int gpioRc; + upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); + gpioupsfd->chipLinesCount=gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); + upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); + if(gpioupsfd->chipLinesCountupsMaxLine) + fatalx( + LOG_ERR, + "GPIO chip lines count %d smaller than UPS line number used (%d)", + gpioupsfd->chipLinesCount, + gpioupsfd->upsMaxLine + ); + gpioupsfd->upsLinesStates=xcalloc(sizeof(int), gpioupsfd->upsLinesCount); + gpiod_line_bulk_init(&libgpiod_data->gpioLines); + gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); + gpioRc=gpiod_chip_get_lines( + libgpiod_data->gpioChipHandle, + (unsigned int *)gpioupsfd->upsLines, + gpioupsfd->upsLinesCount, + &libgpiod_data->gpioLines + ); + if(gpioRc) + fatal_with_errno( + LOG_ERR, + "GPIO line reservation (gpiod_chip_get_lines call) failed with code %d, check for possible issue in rules parameter", + gpioRc + ); + upsdebugx(LOG_DEBUG, "GPIO gpiod_chip_get_lines return code %d", gpioRc); + reserve_lines_libgpiod(gpioupsfd, 0); + } +} + +void gpio_close(struct gpioups_t *gpioupsfd) { + if(gpioupsfd) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + if(libgpiod_data) { + if(libgpiod_data->gpioChipHandle) { + gpiod_chip_close(libgpiod_data->gpioChipHandle); + } + free(gpioupsfd->lib_data); + gpioupsfd->lib_data = NULL; + } + } +} + +/* get GPIO line states for all needed lines */ +void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { + int i; + int gpioRc; + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + reserve_lines_libgpiod(gpioupsfd, 1); + if(gpioupsfd->runOptions&ROPT_EVMODE) { + struct timespec timeoutLong={1,0}; + struct gpiod_line_event event; + int monRes; + upsdebugx( + LOG_DEBUG, + "gpio_get_lines_states_libgpiod initial %d, timeout %ld", + gpioupsfd->initial, + timeoutLong.tv_sec + ); + if(gpioupsfd->initial) { + timeoutLong.tv_sec=35; + } else { + gpioupsfd->initial=1; + } + upsdebugx( + LOG_DEBUG, + "gpio_get_lines_states_libgpiod initial %d, timeout %ld", + gpioupsfd->initial, + timeoutLong.tv_sec + ); + gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); + monRes=gpiod_line_event_wait_bulk( + &libgpiod_data->gpioLines, + &timeoutLong, + &libgpiod_data->gpioEventLines + ); + upsdebugx( + LOG_DEBUG, + "gpiod_line_event_wait_bulk completed with %d return code and timeout %ld s", + monRes, + timeoutLong.tv_sec + ); + if(monRes==1) { + int num_lines=(int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); + int i; + for(i=0; igpioEventLines, + i + ); + int eventRc=gpiod_line_event_read(eLine, &event); + unsigned int lineOffset=gpiod_line_offset(eLine); + event.event_type=0; + upsdebugx( + LOG_DEBUG, + "Event read return code %d and event type %d for line %d", + eventRc, + event.event_type, + lineOffset + ); + } + } + } + for(i=0; iupsLinesCount; i++) { + gpioupsfd->upsLinesStates[i]=-1; + } + gpioRc=gpiod_line_get_value_bulk( + &libgpiod_data->gpioLines, + gpioupsfd->upsLinesStates + ); + if (gpioRc<0) + fatal_with_errno(LOG_ERR, "GPIO line status read call failed"); + upsdebugx( + LOG_DEBUG, + "GPIO gpiod_line_get_value_bulk completed with %d return code, status values:", + gpioRc + ); + for(i=0; iupsLinesCount; i++) { + upsdebugx( + LOG_DEBUG, + "Line%d state = %d", + i, + gpioupsfd->upsLinesStates[i] + ); + } + if(gpioupsfd->runOptions&ROPT_REQRES) { + gpiod_line_release_bulk(&libgpiod_data->gpioLines); + } +} diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h new file mode 100644 index 0000000000..1ddf554355 --- /dev/null +++ b/drivers/generic_gpio_libgpiod.h @@ -0,0 +1,15 @@ +#ifndef GENERIC_GPIO_LIBGPIOD_H +#define GENERIC_GPIO_LIBGPIOD_H + +#define DRIVER_NAME "GPIO UPS driver" +#define DRIVER_VERSION "1.00" + +extern struct gpioups_t *gpioupsfd; + +typedef struct libgpiod_data_t { + struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ + struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ + struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ +} libgpiod_data; + +#endif /* GENERIC_GPIO_LIBGPIOD_H */ From 11735fb4bfb8e7415aed459dba7543c691507616 Mon Sep 17 00:00:00 2001 From: modrisb Date: Sun, 26 Feb 2023 22:55:47 +0200 Subject: [PATCH 0484/1232] PR review #1 (no m4) --- docs/man/Makefile.am | 14 +- docs/man/{gpio.txt => generic_gpio.txt} | 49 ++-- drivers/Makefile.am | 10 +- drivers/generic_gpio_common.c | 291 ++++++++++++------------ drivers/generic_gpio_common.h | 22 +- drivers/generic_gpio_libgpiod.c | 92 ++++---- drivers/generic_gpio_libgpiod.h | 23 ++ 7 files changed, 284 insertions(+), 217 deletions(-) rename docs/man/{gpio.txt => generic_gpio.txt} (70%) diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index ba545f9695..ac12283aea 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -669,16 +669,16 @@ endif HTML_LINUX_I2C_MANS = asem.html pijuice.html -SRC_LINUX_GPIO_PAGES = gpio.txt +SRC_GPIO_PAGES = generic_gpio.txt if WITH_MANS -MAN_LINUX_GPIO_PAGES = gpio.8 +MAN_GPIO_PAGES = generic_gpio.8 endif if WITH_GPIO -man8_MANS += $(MAN_LINUX_GPIO_PAGES) +man8_MANS += $(MAN_GPIO_PAGES) endif -HTML_LINUX_GPIO_MANS = gpio.html +HTML_GPIO_MANS = generic_gpio.html # SOME_DRIVERS endif @@ -703,7 +703,7 @@ MAN_MANS += \ $(MAN_MACOSX_PAGES) \ $(MAN_MODBUS_PAGES) \ $(MAN_LINUX_I2C_PAGES) \ - $(MAN_LINUX_GPIO_PAGES) + $(MAN_GPIO_PAGES) endif SRC_DRIVERS_PAGES = \ @@ -717,7 +717,7 @@ SRC_DRIVERS_PAGES = \ $(SRC_MACOSX_PAGES) \ $(SRC_MODBUS_PAGES) \ $(SRC_LINUX_I2C_PAGES) \ - $(SRC_LINUX_GPIO_PAGES) + $(SRC_GPIO_PAGES) if SOME_DRIVERS # The list above probably came up empty in this case, so make sure that @@ -776,7 +776,7 @@ HTML_MANS = \ $(HTML_MACOSX_MANS) \ $(HTML_MODBUS_MANS) \ $(HTML_LINUX_I2C_MANS) \ - $(HTML_LINUX_GPIO_MANS) + $(HTML_GPIO_MANS) # Note: target documents, except nutupsdrv.txt itself, start the # list of drivers with `- linkman:nutupsdrv[8]` entry diff --git a/docs/man/gpio.txt b/docs/man/generic_gpio.txt similarity index 70% rename from docs/man/gpio.txt rename to docs/man/generic_gpio.txt index 289d4d0246..c9476e3f51 100644 --- a/docs/man/gpio.txt +++ b/docs/man/generic_gpio.txt @@ -1,19 +1,19 @@ GENERIC GPIO(8) -================= +=============== NAME ---- -GENERIC GPIO - Driver for GPIO connected UPS +generic_gpio - Driver for GPIO connected UPSes SYNOPSIS -------- -*GENERIC_GPIO* -h +*generic_gpio* -h -*GENERIC_GPIO* -a 'GPIOCHIP0' ['OPTIONS'] +*generic_gpio* -a 'gpiochip0' ['OPTIONS'] -NOTE: This man page only documents the specific features of the *GPIO* +NOTE: This man page only documents the specific features of the *generic_gpio* driver. For information about the core driver, see linkman:nutupsdrv[8]. SUPPORTED HARDWARE @@ -40,22 +40,30 @@ Driver control: *rules*='value':: A string consisting of sub-strings. Each sub-string describes GPIO line states conversion formula to specific NUT state, like -nut_state=[^]line_num[logical_operation.line_num]. Not (^) , and (&) , or +`nut_state=[^]line_num[logical_operation[^]line_num]...;`. Not (^) , and (&) , or (|)operations are supported for now. nut_state should correspond to NUT state, line_num to GPIO line number connected to UPS open collector pin. CyberShield CSN27U12V describes pins as: -ON BATTERY Low when operating from utility line - Open when operating from battery -REPLACE BATTERY Low when battery is charged - Open when battery fails the Self Test -BATTERY MISSING Low when battery is present - Open when battery is missing -LOW BATTERY Low when battery is near full charge capacity - Open when operating from a battery with < 20% capacity +|=== +|Battery state|State details|GPIO line +|ON BATTERY|*Low* when operating from utility line + +*Open* when operating from battery|0 +|REPLACE BATTERY|*Low* when battery is charged + +*Open* when battery fails the Self Test|1 +|BATTERY MISSING|*Low* when battery is present + +*Open* when battery is missing|6 +|LOW BATTERY|*Low* when battery is near full charge capacity + +*Open* when operating from a battery with < 20% capacity|3 +|=== and rules might be defined as -rules = "OL=^0;OB=0;LB=3;RB=1;DISCHRG=0&^6;BYPASS=6;" -assuming that line 0 is connected to ON BATTERY pin, REPLACE BATTERY to line 1, -BATTERY MISSING pin to line 6 and LOW BATTERY to line 3. Expecting simple formula + +`rules = "OL=^0;OB=0;LB=3;RB=1;DISCHRG=0&^6;BYPASS=6;"` + +assuming battery pin connection to GPIO lines as listed in table. Expecting simple formula to be used for each state, extra may increase state reliability and may need to be checked on each specific UPS. @@ -94,9 +102,10 @@ libgpiod and running `configure --with-gpio=yes`. You also need to give proper permissions on the local serial device file (/dev/gpiochip0 for example) to allow the run-time NUT driver user -account to access it, like by adding the following rule to rules.d directory: -SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ - chown -R nut:nut /dev/gpiochip0 && chmod -R 700 /dev/gpiochip0\ +account to access it, like by adding the following rule to Linux rules.d directory: + + SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ + chown -R nut:nut /dev/gpiochip0 && chmod -R 700 /dev/gpiochip0\ AUTHOR ------ diff --git a/drivers/Makefile.am b/drivers/Makefile.am index c0692cd84a..a1598e1525 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -65,6 +65,7 @@ GPIO_DRIVERLIST = generic_gpio_libgpiod EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) EXTRA_PROGRAMS += $(SNMP_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST) EXTRA_PROGRAMS += $(LINUX_I2C_DRIVERLIST) +EXTRA_PROGRAMS += $(NUTSW_DRIVERLIST) EXTRA_PROGRAMS += $(GPIO_DRIVERLIST) # construct the list of drivers to build @@ -171,11 +172,6 @@ upscode2_LDADD = $(LDADD) -lm victronups_SOURCES = victronups.c riello_ser_SOURCES = riello.c riello_ser.c riello_ser_LDADD = $(LDADD) -lm -#gpio_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c -generic_gpio_libgpiod_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c -#gpio_CFLAGS = $(AM_CFLAGS) -#gpio_LDADD = $(LDADD_DRIVERS) -lgpiod -generic_gpio_libgpiod_LDADD = $(LDADD_DRIVERS) -lgpiod # non-serial drivers: these use custom LDADD and/or CFLAGS @@ -310,6 +306,10 @@ asem_SOURCES = asem.c pijuice_LDADD = $(LDADD_DRIVERS) $(LIBI2C_LIBS) pijuice_SOURCES = pijuice.c +# GPIO drivers +generic_gpio_libgpiod_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c +generic_gpio_libgpiod_LDADD = $(LDADD_DRIVERS) -lgpiod + # nutdrv_qx USB/Serial nutdrv_qx_SOURCES = nutdrv_qx.c nutdrv_qx_LDADD = $(LDADD_DRIVERS) -lm diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index b55a86d4ee..eed544aad3 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -1,59 +1,42 @@ -/* - anything commented is optional - anything else is mandatory - - for more information, refer to: - * docs/developers.txt - * docs/new-drivers.txt - * docs/new-names.txt - - and possibly also to: - * docs/hid-subdrivers.txt for USB/HID devices - * or docs/snmp-subdrivers.txt for SNMP devices -*/ -/* ./configure --with-pidpath=/run/nut --with-altpidpath=/run/nut --with-statepath=/run/nut --sysconfdir=/etc/nut --with-gpio --with-user=nut --with-group=nut */ -#pragma GCC optimize("O0") +/* generic_gpio_common.c - common NUT driver code for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * + * 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 "config.h" #include "main.h" #include "attribute.h" #include "generic_gpio_common.h" -/* CyberPower 12V open collector state definitions - 0 ON BATTERY Low when operating from utility line - Open when operating from battery - 1 REPLACE BATTERY Low when battery is charged - Open when battery fails the Self Test - 6 BATTERY MISSING Low when battery is present - Open when battery is missing - 3 LOW BATTERY Low when battery is near full charge capacity - Open when operating from a battery with < 20% capacity - - NUT supported states - OL On line (mains is present) - OB On battery (mains is not present) - LB Low battery - HB High battery - RB The battery needs to be replaced - CHRG The battery is charging - DISCHRG The battery is discharging (inverter is providing load power) - BYPASS UPS bypass circuit is active -- no battery protection is available - CAL UPS is currently performing runtime calibration (on battery) - OFF UPS is offline and is not supplying power to the load - OVER UPS is overloaded - TRIM UPS is trimming incoming voltage (called "buck" in some hardware) - BOOST UPS is boosting incoming voltage - FSD Forced Shutdown (restricted use, see the note below) - - CyberPower rules setting - OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; -*/ - struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; +static struct gpioups_t *generic_gpio_open(const char *chipName); static void get_ups_rules(struct gpioups_t *upsfd); +static void add_rule_item(struct gpioups_t *upsfd, int newValue); +static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); +static int calc_rule_states(int cRules[], int subCount, int sIndex); +static void update_ups_states(struct gpioups_t *gpioupsfd); -/* open gpiochip, process rules and check lines numbers validity */ +/* + * allocate common data structures and process/check rules + */ static struct gpioups_t *generic_gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ @@ -62,7 +45,9 @@ static struct gpioups_t *generic_gpio_open(const char *chipName) { return upsfdlocal; } -/* close gpiochip and release any allocated resources */ +/* + * release common data structures + */ static void generic_gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd) { if(gpioupsfd->upsLines) { @@ -81,18 +66,23 @@ static void generic_gpio_close(struct gpioups_t *gpioupsfd) { } } -/* add compiled subrules item to the array */ +/* + * add compiled subrules item to the array + */ static void add_rule_item(struct gpioups_t *upsfd, int newValue) { - int subCount=(upsfd->rules[upsfd->rulesCount-1]) ? upsfd->rules[upsfd->rulesCount-1]->subCount+1 : 1; - int itemSize=subCount*sizeof(upsfd->rules[0]->cRules[0])+sizeof(rulesint); - upsfd->rules[upsfd->rulesCount-1]=xrealloc(upsfd->rules[upsfd->rulesCount-1], itemSize); - upsfd->rules[upsfd->rulesCount-1]->subCount=subCount; - upsfd->rules[upsfd->rulesCount-1]->cRules[subCount-1]=newValue; + int subCount = (upsfd->rules[upsfd->rulesCount-1]) ? upsfd->rules[upsfd->rulesCount-1]->subCount+1 : 1; + int itemSize = subCount*sizeof(upsfd->rules[0]->cRules[0])+sizeof(rulesint); + + upsfd->rules[upsfd->rulesCount-1] = xrealloc(upsfd->rules[upsfd->rulesCount-1], itemSize); + upsfd->rules[upsfd->rulesCount-1]->subCount = subCount; + upsfd->rules[upsfd->rulesCount-1]->cRules[subCount-1] = newValue; } -/* get next lexem out of rules configuration string recognizing separators = and ; , -logical commands ^ , & , | , state names - several ascii characters matching NUT states, -and several numbers to denote GPIO chip lines to read statuses */ +/* + * get next lexem out of rules configuration string recognizing separators = and ; , + * logical commands ^ , & , | , state names - several ascii characters matching NUT states, + * and several numbers to denote GPIO chip lines to read statuses + */ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { static unsigned char lexType[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 0x00 */ @@ -112,26 +102,31 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 240 0xf0 */ }; - unsigned char lexTypeChr=lexType[rulesBuff[*startPos]]; - *endPos=(*startPos)+1; - if(lexTypeChr=='a' || lexTypeChr=='0') { - for(; lexType[rulesBuff[*endPos]]==lexTypeChr; (*endPos)++); + unsigned char lexTypeChr = lexType[rulesBuff[*startPos]]; + + *endPos = (*startPos)+1; + if(lexTypeChr == 'a' || lexTypeChr == '0') { + for(; lexType[rulesBuff[*endPos]] == lexTypeChr; (*endPos)++); } return (int)lexTypeChr; } -/* split subrules and translate them to array of commands/line numbers */ +/* + * split subrules and translate them to array of commands/line numbers + */ static void get_ups_rules(struct gpioups_t *upsfd) { - unsigned char *rulesString=(unsigned char *)getval("rules"); + unsigned char *rulesString = (unsigned char *)getval("rules"); /* statename=[^]line[&||[line]] */ char lexBuff[33]; - int startPos=0, endPos; + int startPos = 0, endPos; int lexType; - int lexStatus=0; + int lexStatus = 0; int i, j, k; int tranformationDelta; + upsdebugx(LOG_DEBUG, "rules =[%s]", rulesString); - while((lexType=get_rule_lex(rulesString, &startPos, &endPos))>0 && lexStatus>=0) { + /* state machine to process rules definition */ + while((lexType=get_rule_lex(rulesString, &startPos, &endPos)) > 0 && lexStatus >= 0) { memset(lexBuff, 0, sizeof(lexBuff)); strncpy(lexBuff, (char *)(rulesString+startPos), endPos-startPos); upsdebugx( @@ -144,75 +139,75 @@ static void get_ups_rules(struct gpioups_t *upsfd) { ); switch(lexStatus) { case 0: - if(lexType!='a') { + if(lexType != 'a') { lexStatus=-1; } else { - lexStatus=1; + lexStatus = 1; upsfd->rulesCount++; - upsfd->rules=xrealloc(upsfd->rules, (size_t)(sizeof(upsfd->rules[0])*upsfd->rulesCount)); - upsfd->rules[upsfd->rulesCount-1]=xcalloc(sizeof(rulesint), 1); + upsfd->rules = xrealloc(upsfd->rules, (size_t)(sizeof(upsfd->rules[0])*upsfd->rulesCount)); + upsfd->rules[upsfd->rulesCount-1] = xcalloc(sizeof(rulesint), 1); strncpy(upsfd->rules[upsfd->rulesCount-1]->stateName, (char *)(rulesString+startPos), endPos-startPos); - upsfd->rules[upsfd->rulesCount-1]->stateName[endPos-startPos]=0; + upsfd->rules[upsfd->rulesCount-1]->stateName[endPos-startPos] = 0; } break; case 1: - if(lexType!='=') { - lexStatus=-1; + if(lexType != '=') { + lexStatus = -1; } else { - lexStatus=2; + lexStatus = 2; } break; case 2: - if(lexType=='^') { - lexStatus=3; + if(lexType == '^') { + lexStatus = 3; add_rule_item(upsfd, RULES_CMD_NOT); - } else if(lexType=='0') { - lexStatus=4; + } else if(lexType == '0') { + lexStatus = 4; add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); } else { - lexStatus=-1; + lexStatus = -1; } break; case 3: - if(lexType!='0') { - lexStatus=-1; + if(lexType != '0') { + lexStatus = -1; } else { - lexStatus=4; + lexStatus = 4; add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); } break; case 4: - if(lexType=='&') { - lexStatus=2; + if(lexType == '&') { + lexStatus = 2; add_rule_item(upsfd, RULES_CMD_AND); - } else if(lexType=='|') { - lexStatus=2; + } else if(lexType == '|') { + lexStatus = 2; add_rule_item(upsfd, RULES_CMD_OR); } - else if(lexType==';') { - lexStatus=0; + else if(lexType == ';') { + lexStatus = 0; } else { - lexStatus=-1; + lexStatus = -1; } break; default: - lexStatus=-1; + lexStatus = -1; break; } - if(lexStatus==-1) + if(lexStatus == -1) fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); - startPos=endPos; + startPos = endPos; } upsdebugx(LOG_DEBUG, "rules count [%d]", upsfd->rulesCount); - for(i=0; irulesCount; i++) { + for(i = 0; i < upsfd->rulesCount; i++) { upsdebugx( LOG_DEBUG, "rule state name [%s], subcount %d", upsfd->rules[i]->stateName, upsfd->rules[i]->subCount ); - for(j=0; jrules[i]->subCount; j++) { + for(j = 0; jrules[i]->subCount; j++) { upsdebugx( LOG_DEBUG, "[%s] substate %d [%d]", @@ -223,23 +218,23 @@ static void get_ups_rules(struct gpioups_t *upsfd) { } } - upsfd->upsLinesCount=0; - upsfd->upsMaxLine=0; - for(i=0; irulesCount; i++) { - for(j=0; jrules[i]->subCount; j++) { - int pinOnList=0; - for(k=0; kupsLinesCount && !pinOnList; k++) { - if(upsfd->upsLines[k]==upsfd->rules[i]->cRules[j]) { - pinOnList=1; + upsfd->upsLinesCount = 0; + upsfd->upsMaxLine = 0; + for(i = 0; i < upsfd->rulesCount; i++) { + for(j = 0; j < upsfd->rules[i]->subCount; j++) { + int pinOnList = 0; + for(k = 0; k < upsfd->upsLinesCount && !pinOnList; k++) { + if(upsfd->upsLines[k] == upsfd->rules[i]->cRules[j]) { + pinOnList = 1; } } if(!pinOnList) { - if(upsfd->rules[i]->cRules[j]>=0) { + if(upsfd->rules[i]->cRules[j] >= 0) { upsfd->upsLinesCount++; - upsfd->upsLines=xrealloc(upsfd->upsLines, sizeof(upsfd->upsLines[0])*upsfd->upsLinesCount); - upsfd->upsLines[upsfd->upsLinesCount-1]=upsfd->rules[i]->cRules[j]; - if(upsfd->upsLines[upsfd->upsLinesCount-1]>upsfd->upsMaxLine) { - upsfd->upsMaxLine=upsfd->upsLines[upsfd->upsLinesCount-1]; + upsfd->upsLines = xrealloc(upsfd->upsLines, sizeof(upsfd->upsLines[0])*upsfd->upsLinesCount); + upsfd->upsLines[upsfd->upsLinesCount-1] = upsfd->rules[i]->cRules[j]; + if(upsfd->upsLines[upsfd->upsLinesCount-1] > upsfd->upsMaxLine) { + upsfd->upsMaxLine = upsfd->upsLines[upsfd->upsLinesCount-1]; } } } @@ -247,36 +242,36 @@ static void get_ups_rules(struct gpioups_t *upsfd) { } upsdebugx(LOG_DEBUG, "UPS line count = %d", upsfd->upsLinesCount); - for(i=0; iupsLinesCount; i++) { + for(i = 0; i < upsfd->upsLinesCount; i++) { upsdebugx(LOG_DEBUG, "UPS line%d number %d", i, upsfd->upsLines[i]); } - tranformationDelta=upsfd->upsMaxLine-RULES_CMD_LAST+1; - for(i=0; irulesCount; i++) { - for(j=0; jrules[i]->subCount; j++) { - if(upsfd->rules[i]->cRules[j]>=0) { - upsfd->rules[i]->cRules[j]-=tranformationDelta; + tranformationDelta = upsfd->upsMaxLine - RULES_CMD_LAST + 1; + for(i = 0; i < upsfd->rulesCount; i++) { + for(j = 0; j < upsfd->rules[i]->subCount; j++) { + if(upsfd->rules[i]->cRules[j] >= 0) { + upsfd->rules[i]->cRules[j] -= tranformationDelta; } } } - for(k=0; kupsLinesCount; k++) { - for(i=0; irulesCount; i++) { - for(j=0; jrules[i]->subCount; j++) { - if((upsfd->rules[i]->cRules[j]+tranformationDelta)==upsfd->upsLines[k]) { - upsfd->rules[i]->cRules[j]=k; + for(k = 0; k < upsfd->upsLinesCount; k++) { + for(i = 0; i < upsfd->rulesCount; i++) { + for(j = 0; j < upsfd->rules[i]->subCount; j++) { + if((upsfd->rules[i]->cRules[j] + tranformationDelta) == upsfd->upsLines[k]) { + upsfd->rules[i]->cRules[j] = k; } } } } upsdebugx(LOG_DEBUG, "rules count [%d] translated", upsfd->rulesCount); - for(i=0; irulesCount; i++) { + for(i = 0; i < upsfd->rulesCount; i++) { upsdebugx( LOG_DEBUG, "rule state name [%s], subcount %d translated", upsfd->rules[i]->stateName, upsfd->rules[i]->subCount ); - for(j=0; jrules[i]->subCount; j++) { + for(j = 0; j < upsfd->rules[i]->subCount; j++) { upsdebugx( LOG_DEBUG, "[%s] substate %d [%d]", @@ -287,55 +282,59 @@ static void get_ups_rules(struct gpioups_t *upsfd) { } } -/* calculate state rule value based on GPIO line values */ +/* + * calculate state rule value based on GPIO line values + */ static int calc_rule_states(int cRules[], int subCount, int sIndex) { - int ruleVal=0; - int iopStart=sIndex; + int ruleVal = 0; + int iopStart = sIndex; int rs; - if(iopStart=0) { - ruleVal=gpioupsfd->upsLinesStates[cRules[iopStart]]; + if(iopStart < subCount) { + if(cRules[iopStart] >= 0) { + ruleVal = gpioupsfd->upsLinesStates[cRules[iopStart]]; } else { iopStart++; - ruleVal=!gpioupsfd->upsLinesStates[cRules[iopStart]]; + ruleVal = !gpioupsfd->upsLinesStates[cRules[iopStart]]; } iopStart++; } - if(iopStartupsLinesStates[cRules[iopStart]]; + rs = !gpioupsfd->upsLinesStates[cRules[iopStart]]; } else { - rs=gpioupsfd->upsLinesStates[cRules[iopStart]]; + rs = gpioupsfd->upsLinesStates[cRules[iopStart]]; } - ruleVal= ruleVal && rs; + ruleVal = ruleVal && rs; } } return ruleVal; } -/* set ups state according to rules, do adjustments for CHRG/DISCHRG - and battery charge states */ +/* + * set ups state according to rules, do adjustments for CHRG/DISCHRG + * and battery charge states + */ static void update_ups_states(struct gpioups_t *gpioupsfd) { - int batLow=0; - int chargerStatusSet=0; + int batLow = 0; + int chargerStatusSet = 0; int ruleNo; status_init(); - for(ruleNo=0; ruleNorulesCount; ruleNo++) { - gpioupsfd->rules[ruleNo]->currVal= + for(ruleNo = 0; ruleNo < gpioupsfd->rulesCount; ruleNo++) { + gpioupsfd->rules[ruleNo]->currVal = calc_rule_states( gpioupsfd->rules[ruleNo]->cRules, gpioupsfd->rules[ruleNo]->subCount, 0 ); if(gpioupsfd->rules[ruleNo]->currVal) { status_set(gpioupsfd->rules[ruleNo]->stateName); - + if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "CHRG")) { dstate_setinfo("battery.charger.status", "%s", "charging"); chargerStatusSet++; @@ -345,20 +344,20 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { chargerStatusSet++; } if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "LB")) { - batLow=1; + batLow = 1; } } if(gpioupsfd->aInfoAvailable && - gpioupsfd->rules[ruleNo]->archVal!=gpioupsfd->rules[ruleNo]->currVal) { + gpioupsfd->rules[ruleNo]->archVal != gpioupsfd->rules[ruleNo]->currVal) { upslogx(LOG_WARNING, "UPS state [%s] changed to %d", gpioupsfd->rules[ruleNo]->stateName, gpioupsfd->rules[ruleNo]->currVal ); } - gpioupsfd->rules[ruleNo]->archVal=gpioupsfd->rules[ruleNo]->currVal; + gpioupsfd->rules[ruleNo]->archVal = gpioupsfd->rules[ruleNo]->currVal; } - if(chargerStatusSet<=0) { + if(chargerStatusSet <= 0) { dstate_delinfo("battery.charger.status"); } @@ -370,7 +369,7 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { } } - gpioupsfd->aInfoAvailable=1; + gpioupsfd->aInfoAvailable = 1; status_commit(); } @@ -441,4 +440,4 @@ void upsdrv_cleanup(void) gpio_close(gpioupsfd); /* release related generic resources */ generic_gpio_close(gpioupsfd); -} \ No newline at end of file +} diff --git a/drivers/generic_gpio_common.h b/drivers/generic_gpio_common.h index e25b634e2c..4a591bcc1f 100644 --- a/drivers/generic_gpio_common.h +++ b/drivers/generic_gpio_common.h @@ -1,8 +1,28 @@ #ifndef GENERIC_GPIO_COMMON_H #define GENERIC_GPIO_COMMON_H +/* generic_gpio_common.h - common NUT driver definitions for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * + * 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 -#include #include #include diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 50f075fdfa..f9a65ee2cc 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -1,18 +1,24 @@ -/* - anything commented is optional - anything else is mandatory - - for more information, refer to: - * docs/developers.txt - * docs/new-drivers.txt - * docs/new-names.txt - - and possibly also to: - * docs/hid-subdrivers.txt for USB/HID devices - * or docs/snmp-subdrivers.txt for SNMP devices -*/ -/* ./configure --with-pidpath=/run/nut --with-altpidpath=/run/nut --with-statepath=/run/nut --sysconfdir=/etc/nut --with-gpio --with-user=nut --with-group=nut */ -#pragma GCC optimize("O0") +/* generic_gpio_libgpiod.c - gpiod based NUT driver code for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * + * 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 "config.h" #include "main.h" @@ -120,24 +126,26 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, } #endif -/* reserve GPIO lines as per run options and inner parameter: do reservation once - or per each status read */ +/* + * reserve GPIO lines as per run options and inner parameter: do reservation once + * or per each status read + */ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions %d, inner %d", gpioupsfd->runOptions, inner); - if(((gpioupsfd->runOptions&ROPT_REQRES)!=0)==inner) { + if(((gpioupsfd->runOptions&ROPT_REQRES) != 0) == inner) { struct gpiod_line_request_config config; int gpioRc; config.consumer=upsdrv_info.name; if(gpioupsfd->runOptions&ROPT_EVMODE) { - config.request_type=GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; + config.request_type = GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); } else { - config.request_type=GPIOD_LINE_REQUEST_DIRECTION_INPUT; + config.request_type = GPIOD_LINE_REQUEST_DIRECTION_INPUT; upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_DIRECTION_INPUT"); } - config.flags=0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ - gpioRc=gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL); + config.flags = 0; /* GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; */ + gpioRc = gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL); if(gpioRc) fatal_with_errno( LOG_ERR, @@ -152,11 +160,14 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { } } -/* open gpiochip, process rules and check lines numbers validity */ +/* + * allocate memeory for libary, open gpiochip + * and check lines numbers validity - consistency with h/w chip + */ void gpio_open(struct gpioups_t *gpioupsfd) { struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); - gpioupsfd->lib_data=libgpiod_data; - libgpiod_data->gpioChipHandle=gpiod_chip_open_by_name(gpioupsfd->chipName); + gpioupsfd->lib_data = libgpiod_data; + libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfd->chipName); if(!libgpiod_data->gpioChipHandle) { fatal_with_errno( LOG_ERR, @@ -175,10 +186,10 @@ void gpio_open(struct gpioups_t *gpioupsfd) { gpioupsfd->chipLinesCount, gpioupsfd->upsMaxLine ); - gpioupsfd->upsLinesStates=xcalloc(sizeof(int), gpioupsfd->upsLinesCount); + gpioupsfd->upsLinesStates = xcalloc(sizeof(int), gpioupsfd->upsLinesCount); gpiod_line_bulk_init(&libgpiod_data->gpioLines); gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); - gpioRc=gpiod_chip_get_lines( + gpioRc = gpiod_chip_get_lines( libgpiod_data->gpioChipHandle, (unsigned int *)gpioupsfd->upsLines, gpioupsfd->upsLinesCount, @@ -195,6 +206,9 @@ void gpio_open(struct gpioups_t *gpioupsfd) { } } +/* + * close gpiochip and release allocated memory + */ void gpio_close(struct gpioups_t *gpioupsfd) { if(gpioupsfd) { struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); @@ -208,14 +222,16 @@ void gpio_close(struct gpioups_t *gpioupsfd) { } } -/* get GPIO line states for all needed lines */ +/* + * get GPIO line states for all needed lines + */ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { int i; int gpioRc; struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); reserve_lines_libgpiod(gpioupsfd, 1); if(gpioupsfd->runOptions&ROPT_EVMODE) { - struct timespec timeoutLong={1,0}; + struct timespec timeoutLong = {1,0}; struct gpiod_line_event event; int monRes; upsdebugx( @@ -225,9 +241,9 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { timeoutLong.tv_sec ); if(gpioupsfd->initial) { - timeoutLong.tv_sec=35; + timeoutLong.tv_sec = 35; } else { - gpioupsfd->initial=1; + gpioupsfd->initial = 1; } upsdebugx( LOG_DEBUG, @@ -248,15 +264,15 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { timeoutLong.tv_sec ); if(monRes==1) { - int num_lines=(int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); + int num_lines = (int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); int i; for(i=0; igpioEventLines, i ); int eventRc=gpiod_line_event_read(eLine, &event); - unsigned int lineOffset=gpiod_line_offset(eLine); + unsigned int lineOffset = gpiod_line_offset(eLine); event.event_type=0; upsdebugx( LOG_DEBUG, @@ -268,21 +284,21 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { } } } - for(i=0; iupsLinesCount; i++) { - gpioupsfd->upsLinesStates[i]=-1; + for(i=0; i < gpioupsfd->upsLinesCount; i++) { + gpioupsfd->upsLinesStates[i] = -1; } gpioRc=gpiod_line_get_value_bulk( &libgpiod_data->gpioLines, gpioupsfd->upsLinesStates ); - if (gpioRc<0) + if (gpioRc < 0) fatal_with_errno(LOG_ERR, "GPIO line status read call failed"); upsdebugx( LOG_DEBUG, "GPIO gpiod_line_get_value_bulk completed with %d return code, status values:", gpioRc ); - for(i=0; iupsLinesCount; i++) { + for(i=0; i < gpioupsfd->upsLinesCount; i++) { upsdebugx( LOG_DEBUG, "Line%d state = %d", diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h index 1ddf554355..4725f170bc 100644 --- a/drivers/generic_gpio_libgpiod.h +++ b/drivers/generic_gpio_libgpiod.h @@ -1,5 +1,28 @@ #ifndef GENERIC_GPIO_LIBGPIOD_H #define GENERIC_GPIO_LIBGPIOD_H +/* generic_gpio_libgpiod.h - gpiod based NUT driver definitions for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * + * 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 #define DRIVER_NAME "GPIO UPS driver" #define DRIVER_VERSION "1.00" From e6b1811c415b91385ee6217292d3e6b96864a6f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 26 Feb 2023 23:59:56 +0000 Subject: [PATCH 0485/1232] INSTALL.nut: update instructions for parallel make all + check --- INSTALL.nut | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/INSTALL.nut b/INSTALL.nut index 266f0b7153..5563f81b17 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -365,7 +365,7 @@ This goes similar to usual build and install from Git: :; cd nut :; ./autogen.sh :; ./configure --enable-inplace-runtime # --maybe-some-other-options - :; make -j 4 all check && sudo make install + :; make -j 4 all && make -j 4 check && sudo make install Note that `make install` does not currently handle all the nuances that packaging installation scripts would, such as customizing filesystem @@ -393,7 +393,7 @@ symlinks) and to get them started: :; cd nut :; ./autogen.sh :; ./configure --enable-inplace-runtime # --maybe-some-other-options - :; make -j 4 all check && \ + :; make -j 4 all && make -j 4 check && \ { sudo systemctl stop nut-monitor nut-server || true ; } && \ { sudo systemctl stop nut-driver.service || true ; } && \ { sudo systemctl stop nut-driver.target || true ; } && \ @@ -439,8 +439,14 @@ constructs to just restart the services after installing newly built files (if you know there were no changes to unit file definitions and dependencies), e.g.: - ... - :; make -j 4 all check && \ + :; cd /tmp + :; git clone https://github.com/networkupstools/nut + :; cd nut + :; git checkout -b issue-1234 ### your PR branch name, arbitrary + :; ./autogen.sh + :; ./configure --enable-inplace-runtime # --maybe-some-other-options + ### Iterate your code changes (e.g. PR draft), build and install with: + :; make -j 4 all && make -j 4 check && \ sudo make install && \ sudo systemctl daemon-reload && \ sudo systemd-tmpfiles --create && \ From 17a8ab5ec9b82f3c01583e652b6fa6cdd38f977d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Feb 2023 00:01:02 +0000 Subject: [PATCH 0486/1232] Update docs/nut.dict --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index bbc8bdc5df..46268676ec 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3095 utf-8 +personal_ws-1.1 en 3096 utf-8 AAS ABI ACFAIL @@ -3035,6 +3035,7 @@ wf wget whitespace wiki +wildcards winnutclient winpthreads wmNUT From ff0827af5fbb0e3dfd8d2b280eb9096491e641e1 Mon Sep 17 00:00:00 2001 From: modrisb Date: Mon, 27 Feb 2023 18:10:36 +0200 Subject: [PATCH 0487/1232] added m4 file for driver --- configure.ac | 4 ++ drivers/Makefile.am | 2 +- m4/nut_check_libgpiod.m4 | 85 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 m4/nut_check_libgpiod.m4 diff --git a/configure.ac b/configure.ac index 25ca70187f..c5978caced 100644 --- a/configure.ac +++ b/configure.ac @@ -1541,6 +1541,8 @@ nut_gpio_lib="" NUT_ARG_WITH([gpio], [build and install GPIO driver], [auto]) +NUT_CHECK_LIBGPIO + dnl ${nut_with_gpio}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_gpio}" != "yes"; then nut_with_gpio="no" @@ -3641,6 +3643,8 @@ AC_SUBST(LIBMODBUS_CFLAGS) AC_SUBST(LIBMODBUS_LIBS) AC_SUBST(LIBIPMI_CFLAGS) AC_SUBST(LIBIPMI_LIBS) +AC_SUBST(LIBGPIO_CFLAGS) +AC_SUBST(LIBGPIO_LIBS) AC_SUBST(LIBI2C_LIBS) AC_SUBST(DOC_BUILD_LIST) AC_SUBST(DOC_CHECK_LIST) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index a1598e1525..855926ea0c 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -308,7 +308,7 @@ pijuice_SOURCES = pijuice.c # GPIO drivers generic_gpio_libgpiod_SOURCES = generic_gpio_common.c generic_gpio_libgpiod.c -generic_gpio_libgpiod_LDADD = $(LDADD_DRIVERS) -lgpiod +generic_gpio_libgpiod_LDADD = $(LDADD_DRIVERS) $(LIBGPIO_LIBS) # nutdrv_qx USB/Serial nutdrv_qx_SOURCES = nutdrv_qx.c diff --git a/m4/nut_check_libgpiod.m4 b/m4/nut_check_libgpiod.m4 new file mode 100644 index 0000000000..49d78ccf6a --- /dev/null +++ b/m4/nut_check_libgpiod.m4 @@ -0,0 +1,85 @@ +dnl Check for LIBGPIO compiler flags. On success, set nut_have_gpio="yes" +dnl and set LIBGPIO_CFLAGS and LIBGPIO_LIBS. On failure, set +dnl nut_have_gpio="no". This macro can be run multiple times, but will +dnl do the checking only once. + +AC_DEFUN([NUT_CHECK_LIBGPIO], +[ +if test -z "${nut_have_gpio_seen}"; then + nut_have_gpio_seen=yes + NUT_CHECK_PKGCONFIG + + dnl save CFLAGS and LIBS + CFLAGS_ORIG="${CFLAGS}" + LIBS_ORIG="${LIBS}" + + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [dnl See which version of the gpiod library (if any) is installed + dnl FIXME : Support detection of cflags/ldflags below by legacy + dnl discovery if pkgconfig is not there + AC_MSG_CHECKING(for libgpiod-dev version via pkg-config (1.0.0 minimum required)) + GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion gpiod 2>/dev/null`" + if test "$?" != "0" -o -z "${GPIO_VERSION}"; then + GPIO_VERSION="none" + fi + AC_MSG_RESULT(${GPIO_VERSION} found) + ], + [GPIO_VERSION="none" + AC_MSG_NOTICE([can not check libgpiod settings via pkg-config]) + ] + ) + + AC_MSG_CHECKING(for libgpiod cflags) + AC_ARG_WITH(gpio-includes, + AS_HELP_STRING([@<:@--with-gpio-includes=CFLAGS@:>@], [include flags for the gpiod library]), + [ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-gpio-includes - see docs/configure.txt) + ;; + *) + CFLAGS="${withval}" + ;; + esac + ], [ + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [CFLAGS="`$PKG_CONFIG --silence-errors --cflags gpiod 2>/dev/null`" || CFLAGS="-I/usr/include -I/usr/local/include"], + [CFLAGS="-I/usr/include -I/usr/local/include"] + )] + ) + AC_MSG_RESULT([${CFLAGS}]) + + AC_MSG_CHECKING(for libgpiod ldflags) + AC_ARG_WITH(gpio-libs, + AS_HELP_STRING([@<:@--with-gpio-libs=LIBS@:>@], [linker flags for the gpiod library]), + [ + case "${withval}" in + yes|no) + AC_MSG_ERROR(invalid option --with(out)-gpio-libs - see docs/configure.txt) + ;; + *) + LIBS="${withval}" + ;; + esac + ], [ + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [LIBS="`$PKG_CONFIG --silence-errors --libs gpio 2>/dev/null`" || LIBS="-lgpiod"], + [LIBS="-lgpiod"] + )] + ) + AC_MSG_RESULT([${LIBS}]) + + dnl check if gpiod is usable + AC_CHECK_HEADERS(gpiod.h, [nut_have_gpio=yes], [nut_have_gpio=no], [AC_INCLUDES_DEFAULT]) + AC_CHECK_FUNCS(gpiod_chip_open_by_name gpiod_line_get_value_bulk gpiod_chip_close, [], [nut_have_gpio=no]) + + if test "${nut_have_gpio}" = "yes"; then + LIBGPIO_CFLAGS="${CFLAGS}" + LIBGPIO_LIBS="${LIBS}" + fi + + dnl restore original CFLAGS and LIBS + CFLAGS="${CFLAGS_ORIG}" + LIBS="${LIBS_ORIG}" +fi +]) From 23fbdb47b9e96111af12df2272b43d91f3516445 Mon Sep 17 00:00:00 2001 From: modrisb Date: Mon, 27 Feb 2023 18:24:04 +0200 Subject: [PATCH 0488/1232] naming change for PKG_CONFIG - dev version --- m4/nut_check_libgpiod.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/m4/nut_check_libgpiod.m4 b/m4/nut_check_libgpiod.m4 index 49d78ccf6a..319e1c308c 100644 --- a/m4/nut_check_libgpiod.m4 +++ b/m4/nut_check_libgpiod.m4 @@ -18,7 +18,7 @@ if test -z "${nut_have_gpio_seen}"; then dnl FIXME : Support detection of cflags/ldflags below by legacy dnl discovery if pkgconfig is not there AC_MSG_CHECKING(for libgpiod-dev version via pkg-config (1.0.0 minimum required)) - GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion gpiod 2>/dev/null`" + GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion libgpiod-dev 2>/dev/null`" if test "$?" != "0" -o -z "${GPIO_VERSION}"; then GPIO_VERSION="none" fi @@ -43,7 +43,7 @@ if test -z "${nut_have_gpio_seen}"; then esac ], [ AS_IF([test x"$have_PKG_CONFIG" = xyes], - [CFLAGS="`$PKG_CONFIG --silence-errors --cflags gpiod 2>/dev/null`" || CFLAGS="-I/usr/include -I/usr/local/include"], + [CFLAGS="`$PKG_CONFIG --silence-errors --cflags libgpiod-dev 2>/dev/null`" || CFLAGS="-I/usr/include -I/usr/local/include"], [CFLAGS="-I/usr/include -I/usr/local/include"] )] ) @@ -63,7 +63,7 @@ if test -z "${nut_have_gpio_seen}"; then esac ], [ AS_IF([test x"$have_PKG_CONFIG" = xyes], - [LIBS="`$PKG_CONFIG --silence-errors --libs gpio 2>/dev/null`" || LIBS="-lgpiod"], + [LIBS="`$PKG_CONFIG --silence-errors --libs libgpiod-dev 2>/dev/null`" || LIBS="-lgpiod"], [LIBS="-lgpiod"] )] ) From ed31730560c008e54c47c2344e60286447524c58 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Feb 2023 17:43:31 +0100 Subject: [PATCH 0489/1232] configure.ac: introduce realpath_m4() [#1859] --- configure.ac | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 16f9f8e15a..da7549a195 100644 --- a/configure.ac +++ b/configure.ac @@ -199,6 +199,47 @@ case "${target_os}" in ;; esac +AC_CHECK_PROGS([REALPATH], [realpath], []) +AC_DEFUN([realpath_m4], [ + dnl # resolve links - $1 value (not quoted by caller) + dnl # or its directory may be a softlink + dnl # save into varname $2 + AC_MSG_CHECKING([for "real path" of '$1']) + AS_IF([test -n "$REALPATH"], [ + PRG="`${REALPATH} "$1"`" + ], [ + dnl # Code below was adapted from Apache tomcat startup.sh + PRG="$1" + + while test -h "$PRG" ; do + ls="`ls -ld "$PRG"`" + link="`expr "$ls" : '.*-> \(.*\)$'`" + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`/"$link" + fi + done + + PRGDIR="`dirname "$PRG"`" + PRGDIR="`cd "$PRGDIR" && pwd`" + + while test -h "$PRGDIR" ; do + ls="`ls -ld "$PRGDIR"`" + link="`expr "$ls" : '.*-> \(.*\)$'`" + if expr "$link" : '/.*' > /dev/null; then + PRGDIR="$link" + else + PRGDIR=`dirname "$PRGDIR"`/"$link" + fi + done + + PRG="$PRGDIR/`basename "$PRG"`" + ]) + AC_MSG_RESULT([$PRG]) + $2="$PRG" +]) + dnl Note: this deals with run-time settings so that the newly built dnl programs can be "just executed" to use same configuration files dnl and filesystem object permissions as an older deployment of NUT @@ -234,8 +275,14 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AC_PATH_PROG([DEPLOYED_UPSD], [upsd], [], [${PREFIX_SBINDIR}:${PATH}:/sbin:/usr/sbin:/usr/local/sbin]) dnl ...however "upsc" is a userland tool so should be there: AC_PATH_PROG([DEPLOYED_UPSC], [upsc], [], [${PREFIX_BINDIR}:${PATH}]) - AS_IF([test -x "${DEPLOYED_UPSD}"], [DEPLOYED_SBINDIR="`dirname "${DEPLOYED_UPSD}"`"]) - AS_IF([test -x "${DEPLOYED_UPSC}"], [DEPLOYED_BINDIR="`dirname "${DEPLOYED_UPSC}"`"]) + AS_IF([test -x "${DEPLOYED_UPSD}"], [ + realpath_m4([$DEPLOYED_UPSD], [DEPLOYED_UPSD]) + DEPLOYED_SBINDIR="`dirname "${DEPLOYED_UPSD}"`" + ]) + AS_IF([test -x "${DEPLOYED_UPSC}"], [ + realpath_m4([$DEPLOYED_UPSC], [DEPLOYED_UPSC]) + DEPLOYED_BINDIR="`dirname "${DEPLOYED_UPSC}"`" + ]) DEPLOYED_PREFIX="" AS_IF([test -d "${DEPLOYED_SBINDIR}"], From f276535d4f6ec7501d3f25110088769f38c849a4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Feb 2023 17:45:05 +0100 Subject: [PATCH 0490/1232] configure.ac: refactor realpath_m4() into m4/ax_realpath.m4 [#1859] --- configure.ac | 48 ++++---------------------------------- m4/ax_realpath.m4 | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 43 deletions(-) create mode 100644 m4/ax_realpath.m4 diff --git a/configure.ac b/configure.ac index da7549a195..70add8096c 100644 --- a/configure.ac +++ b/configure.ac @@ -137,6 +137,9 @@ test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}' CFLAGS=${CFLAGS-"-O"} +dnl Note: for practical and platform-independent use, see AX_REALPATH macro +AC_CHECK_PROGS([REALPATH], [realpath], []) + dnl NOTE: for definition of NUT_* autoconf macros, see m4/ directory dnl and docs/macros.txt @@ -199,47 +202,6 @@ case "${target_os}" in ;; esac -AC_CHECK_PROGS([REALPATH], [realpath], []) -AC_DEFUN([realpath_m4], [ - dnl # resolve links - $1 value (not quoted by caller) - dnl # or its directory may be a softlink - dnl # save into varname $2 - AC_MSG_CHECKING([for "real path" of '$1']) - AS_IF([test -n "$REALPATH"], [ - PRG="`${REALPATH} "$1"`" - ], [ - dnl # Code below was adapted from Apache tomcat startup.sh - PRG="$1" - - while test -h "$PRG" ; do - ls="`ls -ld "$PRG"`" - link="`expr "$ls" : '.*-> \(.*\)$'`" - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`/"$link" - fi - done - - PRGDIR="`dirname "$PRG"`" - PRGDIR="`cd "$PRGDIR" && pwd`" - - while test -h "$PRGDIR" ; do - ls="`ls -ld "$PRGDIR"`" - link="`expr "$ls" : '.*-> \(.*\)$'`" - if expr "$link" : '/.*' > /dev/null; then - PRGDIR="$link" - else - PRGDIR=`dirname "$PRGDIR"`/"$link" - fi - done - - PRG="$PRGDIR/`basename "$PRG"`" - ]) - AC_MSG_RESULT([$PRG]) - $2="$PRG" -]) - dnl Note: this deals with run-time settings so that the newly built dnl programs can be "just executed" to use same configuration files dnl and filesystem object permissions as an older deployment of NUT @@ -276,11 +238,11 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ dnl ...however "upsc" is a userland tool so should be there: AC_PATH_PROG([DEPLOYED_UPSC], [upsc], [], [${PREFIX_BINDIR}:${PATH}]) AS_IF([test -x "${DEPLOYED_UPSD}"], [ - realpath_m4([$DEPLOYED_UPSD], [DEPLOYED_UPSD]) + AX_REALPATH([$DEPLOYED_UPSD], [DEPLOYED_UPSD]) DEPLOYED_SBINDIR="`dirname "${DEPLOYED_UPSD}"`" ]) AS_IF([test -x "${DEPLOYED_UPSC}"], [ - realpath_m4([$DEPLOYED_UPSC], [DEPLOYED_UPSC]) + AX_REALPATH([$DEPLOYED_UPSC], [DEPLOYED_UPSC]) DEPLOYED_BINDIR="`dirname "${DEPLOYED_UPSC}"`" ]) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 new file mode 100644 index 0000000000..88d6afab6a --- /dev/null +++ b/m4/ax_realpath.m4 @@ -0,0 +1,59 @@ +dnl Resolve given path (if we can), for filenames that may be symlinks, +dnl or in a relative directory, or where directories are symlinks... +dnl Copyright (C) 2023 by Jim Klimov +dnl Licensed under the terms of GPLv2 or newer. + +dnl Calling script is welcome to pre-detect external REALPATH implementation: +dnl AC_CHECK_PROGS([REALPATH], [realpath], []) +AC_DEFUN([AX_REALPATH], +[ + dnl # resolve links - #1 value (not quoted by caller) + dnl # or its directory may be a softlink + dnl # save into varname #2 + AC_MSG_CHECKING([for "real path" of '$1']) + + REALPRG="" + AS_IF([test -n "$REALPATH"], [ + REALPRG="`${REALPATH} "$1"`" + ]) + + AS_IF([test -z "$REALPRG"], [ + dnl # Code below was adapted from Apache Tomcat startup.sh + PRG="$1" + + while test -h "$PRG" ; do + LS_OUT="`ls -ld "$PRG"`" + LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" + if expr "$LINK" : '/.*' > /dev/null; then + PRG="$LINK" + else + PRG="`dirname "$PRG"`/$LINK" + fi + done + + PRGDIR="`dirname "$PRG"`" + PRGDIR="`cd "$PRGDIR" && pwd`" + + while test -h "$PRGDIR" ; do + LS_OUT="`ls -ld "$PRGDIR"`" + LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" + if expr "$LINK" : '/.*' > /dev/null; then + PRGDIR="$LINK" + else + PARENTDIR="`dirname "$PRGDIR"`" + case "$PARENTDIR" in + /) PRGDIR="/$LINK" ; break ;; + *) PRGDIR="$PARENTDIR/$LINK" ;; + esac + fi + done + + REALPRG="$PRGDIR/`basename "$PRG"`" + unset PRG PRGDIR PARENTDIR LS_OUT LINK + ]) + + AC_MSG_RESULT([$REALPRG]) + $2="$REALPRG" + + unset REALPRG +]) From 8edc7500f2a1171c1e781c4f57e3e57edde71408 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Feb 2023 18:26:58 +0100 Subject: [PATCH 0491/1232] m4/ax_realpath.m4: add some error-checking for unresolved paths [#1859] --- m4/ax_realpath.m4 | 58 +++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 88d6afab6a..bf52aa69f4 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -20,10 +20,16 @@ AC_DEFUN([AX_REALPATH], AS_IF([test -z "$REALPRG"], [ dnl # Code below was adapted from Apache Tomcat startup.sh PRG="$1" + RESOLVE_ERROR=0 + + if test \! -e "$PRG" ; then + AC_MSG_WARN([Path name '$PRG' not resolved (absent or access to ancestor directotries denied)]) + RESOLVE_ERROR=1 + fi while test -h "$PRG" ; do - LS_OUT="`ls -ld "$PRG"`" - LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" + LS_OUT="`ls -ld "$PRG"`" || { RESOLVE_ERROR=$? ; break ; } + LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } if expr "$LINK" : '/.*' > /dev/null; then PRG="$LINK" else @@ -31,29 +37,43 @@ AC_DEFUN([AX_REALPATH], fi done - PRGDIR="`dirname "$PRG"`" - PRGDIR="`cd "$PRGDIR" && pwd`" + if test "$RESOLVE_ERROR" = 0 ; then + PRGDIR="`dirname "$PRG"`" && \ + PRGDIR="`cd "$PRGDIR" && pwd`" || { + PRGDIR="`dirname "$PRG"`" || \ + RESOLVE_ERROR=$? ; } - while test -h "$PRGDIR" ; do - LS_OUT="`ls -ld "$PRGDIR"`" - LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" - if expr "$LINK" : '/.*' > /dev/null; then - PRGDIR="$LINK" - else - PARENTDIR="`dirname "$PRGDIR"`" - case "$PARENTDIR" in - /) PRGDIR="/$LINK" ; break ;; - *) PRGDIR="$PARENTDIR/$LINK" ;; - esac + if test "$RESOLVE_ERROR" = 0 ; then + while test -h "$PRGDIR" ; do + LS_OUT="`ls -ld "$PRGDIR"`" || { RESOLVE_ERROR=$? ; break ; } + LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } + if expr "$LINK" : '/.*' > /dev/null; then + PRGDIR="$LINK" + else + PARENTDIR="`dirname "$PRGDIR"`" + case "$PARENTDIR" in + /) PRGDIR="/$LINK" ; break ;; + *) PRGDIR="$PARENTDIR/$LINK" ;; + esac + fi + done fi - done + fi - REALPRG="$PRGDIR/`basename "$PRG"`" + if test "$RESOLVE_ERROR" = 0 ; then + REALPRG="$PRGDIR/`basename "$PRG"`" + fi unset PRG PRGDIR PARENTDIR LS_OUT LINK ]) - AC_MSG_RESULT([$REALPRG]) - $2="$REALPRG" + AS_IF([test -n "$REALPRG"], [ + AC_MSG_RESULT([$REALPRG]) + $2="$REALPRG" + ], [ + dnl Indent due to newline from warning and/or tool errors above + AC_MSG_RESULT([...failed to resolve, keeping original: $1]) + $2="$1" + ]) unset REALPRG ]) From 1f26361afd7859211bdda153d65faf13877b3e7d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 11:15:25 +0100 Subject: [PATCH 0492/1232] m4/ax_realpath.m4: introduce UNITTEST_AX_REALPATH [#1859] --- m4/ax_realpath.m4 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index bf52aa69f4..fdaef1f52c 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -77,3 +77,32 @@ AC_DEFUN([AX_REALPATH], unset REALPRG ]) + +AC_DEFUN([UNITTEST_AX_REALPATH], +[ + AC_MSG_NOTICE([======= starting UNITTEST for REALPATH macro]) + AC_MSG_NOTICE([Testing macro for realpath; /tmp/q/x are directories, qwe is a file inside, and /tmp/Q is a symlink to /tmp/q]) + rm -rf /tmp/q ; mkdir -p /tmp/q/x ; echo qwe > /tmp/q/x/qwe ; ln -fs q /tmp/Q + AX_REALPATH([/tmp/Q/x], [TMPNAME]) + AX_REALPATH([/tmp/Q/x/qwe], [TMPNAME]) + AC_MSG_NOTICE([Got: $TMPNAME (should be /tmp/q/x/qwe)]) + AX_REALPATH([/etc/nut/ups.conf], [TMPNAME]) + AX_REALPATH([/proc/$$/exe], [TMPNAME]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should not have access to next file (does not exist) in a readable dir]) + AX_REALPATH([/tmp/q/x/absent], [TMPNAME]) + AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should not have access to next file (does not exist) in a SYMLINK to readable dir]) + AX_REALPATH([/tmp/Q/x/absent], [TMPNAME]) + AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should not have access to next SYMLINK (reading link content is forbidden)]) + AX_REALPATH([/proc/1/exe], [TMPNAME]) + AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should not have access to next dir (don't know if file exists)]) + AX_REALPATH([/proc/1/fd/1], [TMPNAME]) + AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([======= end of UNITTEST for REALPATH macro]) +]) From 55c3377c6ddfa7f4339b9242e3e0058480c40c9a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 11:15:55 +0100 Subject: [PATCH 0493/1232] configure.ac: TEMPORARY: add call to UNITTEST_AX_REALPATH and exit after it [#1859] --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 70add8096c..7a0d196bcd 100644 --- a/configure.ac +++ b/configure.ac @@ -140,6 +140,10 @@ CFLAGS=${CFLAGS-"-O"} dnl Note: for practical and platform-independent use, see AX_REALPATH macro AC_CHECK_PROGS([REALPATH], [realpath], []) +dnl FIXME: remove after dev-testing +UNITTEST_AX_REALPATH +exit + dnl NOTE: for definition of NUT_* autoconf macros, see m4/ directory dnl and docs/macros.txt From 2711290ff688c474a9a3023e30b30b78bca9d968 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 12:19:20 +0100 Subject: [PATCH 0494/1232] m4/ax_realpath.m4: refactor UNITTEST_AX_REALPATH() with UNITTEST_AX_REALPATH_EXPECT() helper [#1859] --- m4/ax_realpath.m4 | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index fdaef1f52c..552774e263 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -78,31 +78,43 @@ AC_DEFUN([AX_REALPATH], unset REALPRG ]) +AC_DEFUN([UNITTEST_AX_REALPATH_EXPECT], +[ + AX_REALPATH([$1], [TMPNAME]) + AS_IF([test x"$TMPNAME" != x"$2"], [AC_MSG_WARN([Got: $TMPNAME (should be $2)])]) +]) + AC_DEFUN([UNITTEST_AX_REALPATH], [ AC_MSG_NOTICE([======= starting UNITTEST for REALPATH macro]) AC_MSG_NOTICE([Testing macro for realpath; /tmp/q/x are directories, qwe is a file inside, and /tmp/Q is a symlink to /tmp/q]) rm -rf /tmp/q ; mkdir -p /tmp/q/x ; echo qwe > /tmp/q/x/qwe ; ln -fs q /tmp/Q - AX_REALPATH([/tmp/Q/x], [TMPNAME]) - AX_REALPATH([/tmp/Q/x/qwe], [TMPNAME]) - AC_MSG_NOTICE([Got: $TMPNAME (should be /tmp/q/x/qwe)]) - AX_REALPATH([/etc/nut/ups.conf], [TMPNAME]) - AX_REALPATH([/proc/$$/exe], [TMPNAME]) + AC_MSG_NOTICE([=======]) + UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x], [/tmp/q/x]) + UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x], [/tmp/q/x]) + UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/qwe], [/tmp/q/x/qwe]) AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([Should not have access to next file (does not exist) in a readable dir]) - AX_REALPATH([/tmp/q/x/absent], [TMPNAME]) - AC_MSG_NOTICE([Got: $TMPNAME]) + UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x/absent], [/tmp/q/x/absent]) AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([Should not have access to next file (does not exist) in a SYMLINK to readable dir]) - AX_REALPATH([/tmp/Q/x/absent], [TMPNAME]) + UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/absent], [/tmp/q/x/absent]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Present and visible or not, unless this is (behind) a symlink it should remain the same path]) + UNITTEST_AX_REALPATH_EXPECT([/etc/nut/ups.conf], [/etc/nut/ups.conf]) + AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should be a shell interpreter here (if procfs is supported on the platform)]) + AX_REALPATH([/proc/$$/exe], [TMPNAME]) AC_MSG_NOTICE([Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should not have access to next SYMLINK (reading link content is forbidden)]) - AX_REALPATH([/proc/1/exe], [TMPNAME]) + AC_MSG_NOTICE([Should be an stdin socket here (if procfs is supported on the platform)]) + AX_REALPATH([/proc/$$/fd/1], [TMPNAME]) AC_MSG_NOTICE([Got: $TMPNAME]) AC_MSG_NOTICE([=======]) + AC_MSG_NOTICE([Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) + UNITTEST_AX_REALPATH_EXPECT([/proc/1/exe], [/proc/1/exe]) + AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([Should not have access to next dir (don't know if file exists)]) - AX_REALPATH([/proc/1/fd/1], [TMPNAME]) - AC_MSG_NOTICE([Got: $TMPNAME]) + UNITTEST_AX_REALPATH_EXPECT([/proc/1/fd/1], [/proc/1/fd/1]) AC_MSG_NOTICE([======= end of UNITTEST for REALPATH macro]) ]) From 8f5eb974d824bea4f19d62cc7ef1aad2af9a898e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 12:22:31 +0100 Subject: [PATCH 0495/1232] m4/ax_realpath.m4: format messages in UNITTEST_AX_REALPATH() and UNITTEST_AX_REALPATH_EXPECT() in a friendlier fashion [#1859] --- m4/ax_realpath.m4 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 552774e263..bd16c7ead9 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -81,40 +81,40 @@ AC_DEFUN([AX_REALPATH], AC_DEFUN([UNITTEST_AX_REALPATH_EXPECT], [ AX_REALPATH([$1], [TMPNAME]) - AS_IF([test x"$TMPNAME" != x"$2"], [AC_MSG_WARN([Got: $TMPNAME (should be $2)])]) + AS_IF([test x"$TMPNAME" != x"$2"], [AC_MSG_WARN([>>> Got: $TMPNAME (should be $2)])]) ]) AC_DEFUN([UNITTEST_AX_REALPATH], [ AC_MSG_NOTICE([======= starting UNITTEST for REALPATH macro]) - AC_MSG_NOTICE([Testing macro for realpath; /tmp/q/x are directories, qwe is a file inside, and /tmp/Q is a symlink to /tmp/q]) + AC_MSG_NOTICE([### Testing macro for realpath; /tmp/q/x are directories, qwe is a file inside, and /tmp/Q is a symlink to /tmp/q]) rm -rf /tmp/q ; mkdir -p /tmp/q/x ; echo qwe > /tmp/q/x/qwe ; ln -fs q /tmp/Q AC_MSG_NOTICE([=======]) UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x], [/tmp/q/x]) UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x], [/tmp/q/x]) UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/qwe], [/tmp/q/x/qwe]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should not have access to next file (does not exist) in a readable dir]) + AC_MSG_NOTICE([### Should not have access to next file (does not exist) in a readable dir]) UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x/absent], [/tmp/q/x/absent]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should not have access to next file (does not exist) in a SYMLINK to readable dir]) + AC_MSG_NOTICE([### Should not have access to next file (does not exist) in a SYMLINK to readable dir]) UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/absent], [/tmp/q/x/absent]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Present and visible or not, unless this is (behind) a symlink it should remain the same path]) + AC_MSG_NOTICE([### Present and visible or not, unless this is (behind) a symlink it should remain the same path]) UNITTEST_AX_REALPATH_EXPECT([/etc/nut/ups.conf], [/etc/nut/ups.conf]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should be a shell interpreter here (if procfs is supported on the platform)]) + AC_MSG_NOTICE([### Should be a shell interpreter here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/exe], [TMPNAME]) - AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([>>> Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should be an stdin socket here (if procfs is supported on the platform)]) + AC_MSG_NOTICE([### Should be an stdin socket here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/fd/1], [TMPNAME]) - AC_MSG_NOTICE([Got: $TMPNAME]) + AC_MSG_NOTICE([>>> Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) + AC_MSG_NOTICE([### Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/exe], [/proc/1/exe]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([Should not have access to next dir (don't know if file exists)]) + AC_MSG_NOTICE([### Should not have access to next dir (don't know if file exists)]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/fd/1], [/proc/1/fd/1]) AC_MSG_NOTICE([======= end of UNITTEST for REALPATH macro]) ]) From 32a6769c2fd4113e24b8930477780c1db1c3afc6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 12:27:59 +0100 Subject: [PATCH 0496/1232] m4/ax_realpath.m4: UNITTEST_AX_REALPATH(): avoid using /tmp directly if possible [#1859] --- m4/ax_realpath.m4 | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index bd16c7ead9..139ceeb729 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -87,34 +87,37 @@ AC_DEFUN([UNITTEST_AX_REALPATH_EXPECT], AC_DEFUN([UNITTEST_AX_REALPATH], [ AC_MSG_NOTICE([======= starting UNITTEST for REALPATH macro]) - AC_MSG_NOTICE([### Testing macro for realpath; /tmp/q/x are directories, qwe is a file inside, and /tmp/Q is a symlink to /tmp/q]) - rm -rf /tmp/q ; mkdir -p /tmp/q/x ; echo qwe > /tmp/q/x/qwe ; ln -fs q /tmp/Q + AC_MSG_NOTICE([=== Testing macro for realpath; .../q/x are directories, qwe is a file inside, and .../Q is a symlink to .../q]) + TESTDIR="`mktemp -d`" && test -d "$TESTDIR" && test -w "$TESTDIR" || TESTDIR="/tmp" + rm -rf "$TESTDIR"/q ; mkdir -p "$TESTDIR"/q/x ; echo qwe > "$TESTDIR"/q/x/qwe ; ln -fs q "$TESTDIR"/Q + dnl Do not quote TESTDIR in macro calls below, shell quotes are added in implem AC_MSG_NOTICE([=======]) - UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x], [/tmp/q/x]) - UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x], [/tmp/q/x]) - UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/qwe], [/tmp/q/x/qwe]) + UNITTEST_AX_REALPATH_EXPECT([$TESTDIR/q/x], [$TESTDIR/q/x]) + UNITTEST_AX_REALPATH_EXPECT([$TESTDIR/Q/x], [$TESTDIR/q/x]) + UNITTEST_AX_REALPATH_EXPECT([$TESTDIR/Q/x/qwe], [$TESTDIR/q/x/qwe]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should not have access to next file (does not exist) in a readable dir]) - UNITTEST_AX_REALPATH_EXPECT([/tmp/q/x/absent], [/tmp/q/x/absent]) + AC_MSG_NOTICE([=== Should not have access to next file (does not exist) in a readable dir]) + UNITTEST_AX_REALPATH_EXPECT([$TESTDIR/q/x/absent], [$TESTDIR/q/x/absent]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should not have access to next file (does not exist) in a SYMLINK to readable dir]) - UNITTEST_AX_REALPATH_EXPECT([/tmp/Q/x/absent], [/tmp/q/x/absent]) + AC_MSG_NOTICE([=== Should not have access to next file (does not exist) in a SYMLINK to readable dir]) + UNITTEST_AX_REALPATH_EXPECT([$TESTDIR/Q/x/absent], [$TESTDIR/q/x/absent]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Present and visible or not, unless this is (behind) a symlink it should remain the same path]) + AC_MSG_NOTICE([=== Present and visible or not, unless this is (behind) a symlink it should remain the same path]) UNITTEST_AX_REALPATH_EXPECT([/etc/nut/ups.conf], [/etc/nut/ups.conf]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should be a shell interpreter here (if procfs is supported on the platform)]) + AC_MSG_NOTICE([=== Should be a shell interpreter here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/exe], [TMPNAME]) AC_MSG_NOTICE([>>> Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should be an stdin socket here (if procfs is supported on the platform)]) + AC_MSG_NOTICE([=== Should be an stdin socket here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/fd/1], [TMPNAME]) AC_MSG_NOTICE([>>> Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) + AC_MSG_NOTICE([=== Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/exe], [/proc/1/exe]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([### Should not have access to next dir (don't know if file exists)]) + AC_MSG_NOTICE([=== Should not have access to next dir (don't know if file exists)]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/fd/1], [/proc/1/fd/1]) AC_MSG_NOTICE([======= end of UNITTEST for REALPATH macro]) + AS_IF([test x"$TESTDIR" = x"/tmp"], [rm -rf "$TESTDIR/q" "$TESTDIR/Q"], [rm -rf "$TESTDIR"]) ]) From cef7311053419130cb72e9ff387feba66933a2a6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 12:29:25 +0100 Subject: [PATCH 0497/1232] m4/ax_realpath.m4: UNITTEST_AX_REALPATH(): reword a test description [#1859] --- m4/ax_realpath.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 139ceeb729..d0930deb74 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -113,10 +113,10 @@ AC_DEFUN([UNITTEST_AX_REALPATH], AX_REALPATH([/proc/$$/fd/1], [TMPNAME]) AC_MSG_NOTICE([>>> Got: $TMPNAME]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([=== Should not have access to next SYMLINK (reading link content is forbidden), if procfs is supported on the platform and if not root]) + AC_MSG_NOTICE([=== Should not have access to next SYMLINK (reading link content is forbidden, if procfs is supported on the platform and if not root)]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/exe], [/proc/1/exe]) AC_MSG_NOTICE([=======]) - AC_MSG_NOTICE([=== Should not have access to next dir (don't know if file exists)]) + AC_MSG_NOTICE([=== Should not have access to next dir (don't know if file exists, if procfs is supported on the platform and if not root)]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/fd/1], [/proc/1/fd/1]) AC_MSG_NOTICE([======= end of UNITTEST for REALPATH macro]) AS_IF([test x"$TESTDIR" = x"/tmp"], [rm -rf "$TESTDIR/q" "$TESTDIR/Q"], [rm -rf "$TESTDIR"]) From 27eda80ea64350c84f20e2ebc1f04a6383ae4bef Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 12:58:27 +0100 Subject: [PATCH 0498/1232] m4/ax_realpath.m4: UNITTEST_AX_REALPATH(): relocate shell logic into AX_REALPATH_SHELL_RECURSIVE() [#1859] --- m4/ax_realpath.m4 | 101 ++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index d0930deb74..3bfde67a40 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -3,57 +3,57 @@ dnl or in a relative directory, or where directories are symlinks... dnl Copyright (C) 2023 by Jim Klimov dnl Licensed under the terms of GPLv2 or newer. -dnl Calling script is welcome to pre-detect external REALPATH implementation: +dnl Calling script is welcome to pre-detect external REALPATH implementation, +dnl otherwise shell implementation would be used (hopefully capable enough): dnl AC_CHECK_PROGS([REALPATH], [realpath], []) -AC_DEFUN([AX_REALPATH], + +AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], [ - dnl # resolve links - #1 value (not quoted by caller) - dnl # or its directory may be a softlink - dnl # save into varname #2 - AC_MSG_CHECKING([for "real path" of '$1']) + dnl # resolve links - #1 value (not quoted by caller) or some its + dnl # ancestor directory may be a symlink; save into varname #2. + dnl # In case of problems return #1 and set non-zero RESOLVE_ERROR + dnl # Recursion depth in #3 impacts local variable naming + dnl # to recurse backwards from original name to root "/" + dnl # (or abort mid-way). - REALPRG="" - AS_IF([test -n "$REALPATH"], [ - REALPRG="`${REALPATH} "$1"`" - ]) + AS_IF([test x"$1" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg1)])]) + AS_IF([test x"$2" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg2)])]) + AS_IF([test x"$3" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg3)])]) + AS_IF([test x"$RESOLVE_ERROR" = x], [RESOLVE_ERROR=0]) - AS_IF([test -z "$REALPRG"], [ + AS_IF([test x"$RESOLVE_ERROR" != x0], [dnl Quick bail out + $2="$1" + ], [ dnl # Code below was adapted from Apache Tomcat startup.sh - PRG="$1" - RESOLVE_ERROR=0 + TGT$3="$1" - if test \! -e "$PRG" ; then - AC_MSG_WARN([Path name '$PRG' not resolved (absent or access to ancestor directotries denied)]) - RESOLVE_ERROR=1 - fi - - while test -h "$PRG" ; do - LS_OUT="`ls -ld "$PRG"`" || { RESOLVE_ERROR=$? ; break ; } + while test -h "$TGT$3" ; do + LS_OUT="`ls -ld "$TGT$3"`" || { RESOLVE_ERROR=$? ; break ; } LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } if expr "$LINK" : '/.*' > /dev/null; then - PRG="$LINK" + TGT$3="$LINK" else - PRG="`dirname "$PRG"`/$LINK" + TGT$3="`dirname "$TGT$3"`/$LINK" fi done if test "$RESOLVE_ERROR" = 0 ; then - PRGDIR="`dirname "$PRG"`" && \ - PRGDIR="`cd "$PRGDIR" && pwd`" || { - PRGDIR="`dirname "$PRG"`" || \ + TGTDIR$3="`dirname "$TGT$3"`" && \ + TGTDIR$3="`cd "$TGTDIR$3" && pwd`" || { + TGTDIR$3="`dirname "$TGT$3"`" || \ RESOLVE_ERROR=$? ; } if test "$RESOLVE_ERROR" = 0 ; then - while test -h "$PRGDIR" ; do - LS_OUT="`ls -ld "$PRGDIR"`" || { RESOLVE_ERROR=$? ; break ; } + while test -h "$TGTDIR$3" ; do + LS_OUT="`ls -ld "$TGTDIR$3"`" || { RESOLVE_ERROR=$? ; break ; } LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } if expr "$LINK" : '/.*' > /dev/null; then - PRGDIR="$LINK" + TGTDIR$3="$LINK" else - PARENTDIR="`dirname "$PRGDIR"`" - case "$PARENTDIR" in - /) PRGDIR="/$LINK" ; break ;; - *) PRGDIR="$PARENTDIR/$LINK" ;; + PARENTDIR$3="`dirname "$TGTDIR$3"`" + case "$PARENTDIR$3" in + /) TGTDIR$3="/$LINK" ; break ;; + *) TGTDIR$3="$PARENTDIR$3/$LINK" ;; esac fi done @@ -61,9 +61,40 @@ AC_DEFUN([AX_REALPATH], fi if test "$RESOLVE_ERROR" = 0 ; then - REALPRG="$PRGDIR/`basename "$PRG"`" + $2="$TGTDIR$3/`basename "$TGT$3"`" + else + $2="$1" fi - unset PRG PRGDIR PARENTDIR LS_OUT LINK + + unset TGT$3 TGTDIR$3 PARENTDIR$3 + unset LS_OUT LINK + ]) +]) + +AC_DEFUN([AX_REALPATH], +[ + dnl # resolve links - #1 value (not quoted by caller) + dnl # or its directory may be a softlink + dnl # save into varname #2 + AS_IF([test x"$1" = x], [AC_MSG_ERROR([Bad call to REALPATH macro (arg1)])]) + AS_IF([test x"$2" = x], [AC_MSG_ERROR([Bad call to REALPATH macro (arg2)])]) + + AC_MSG_CHECKING([for "real path" of '$1']) + + REALPRG="" + AS_IF([test -n "$REALPATH"], [ + REALPRG="`${REALPATH} "$1"`" + ]) + + AS_IF([test -z "$REALPRG"], [ + RESOLVE_ERROR=0 + + AS_IF([test -e "$PRG"], [ + AC_MSG_WARN([Path name '$PRG' not resolved (absent or access to ancestor directories denied)]) + RESOLVE_ERROR=1 + ], [ + AX_REALPATH_SHELL_RECURSIVE([$1], [REALPRG], [0]) + ]) ]) AS_IF([test -n "$REALPRG"], [ @@ -75,7 +106,7 @@ AC_DEFUN([AX_REALPATH], $2="$1" ]) - unset REALPRG + unset REALPRG RESOLVE_ERROR ]) AC_DEFUN([UNITTEST_AX_REALPATH_EXPECT], From 62f5264e8d2deb85f5752c8a054cdae5516dca43 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:02:01 +0100 Subject: [PATCH 0499/1232] m4/ax_realpath.m4: split AX_REALPATH_SHELL_RECURSIVE() into a loop and its called method [#1859] --- m4/ax_realpath.m4 | 62 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 3bfde67a40..40d42ef04b 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -7,7 +7,7 @@ dnl Calling script is welcome to pre-detect external REALPATH implementation, dnl otherwise shell implementation would be used (hopefully capable enough): dnl AC_CHECK_PROGS([REALPATH], [realpath], []) -AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], +AC_DEFUN([AX_REALPATH_SHELL_ONELEVEL], [ dnl # resolve links - #1 value (not quoted by caller) or some its dnl # ancestor directory may be a symlink; save into varname #2. @@ -16,12 +16,12 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], dnl # to recurse backwards from original name to root "/" dnl # (or abort mid-way). - AS_IF([test x"$1" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg1)])]) - AS_IF([test x"$2" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg2)])]) - AS_IF([test x"$3" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_RECURSIVE macro (arg3)])]) + AS_IF([test x"$1" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg1)])]) + AS_IF([test x"$2" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg2)])]) + AS_IF([test x"$3" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg3)])]) AS_IF([test x"$RESOLVE_ERROR" = x], [RESOLVE_ERROR=0]) - AS_IF([test x"$RESOLVE_ERROR" != x0], [dnl Quick bail out + AS_IF([test x"$RESOLVE_ERROR" != x0 || test x"$1" = x/], [dnl Quick bail out $2="$1" ], [ dnl # Code below was adapted from Apache Tomcat startup.sh @@ -71,6 +71,56 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], ]) ]) +AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], +[ + dnl Autoconf/m4 is not really friendly for recursive functions + dnl so we have to do it like a loop. Sanity-checking is in the + dnl helper method above and will abort the script upon problems. + dnl The RESOLVE_ERROR is provided and unset by caller. + + LVL=0 + RESOLVE_PREFIX="$1" + RESOLVE_SUFFIX="" + + while \ + test x"$RESOLVE_PREFIX" != x \ + && test x"$RESOLVE_PREFIX" != x/ \ + && test x"$RESOLVE_ERROR" = x0 \ + ; do + dnl In case of non-fatal resolve error, value in RESOLVE_PREFIX + dnl should remain unchanged, and a RESOLVE_ERROR flag raised. + AX_REALPATH_SHELL_ONELEVEL([$RESOLVE_PREFIX], [RESOLVE_PREFIX], [0]) + if test x"$RESOLVE_ERROR" = x0 ; then + dnl Recurse to check the (grand)parent dir (if any) + if test -n "$RESOLVE_SUFFIX" ; then + RESOLVE_SUFFIX="`basename "$RESOLVE_PREFIX"`/$RESOLVE_SUFFIX" + else + RESOLVE_SUFFIX="`basename "$RESOLVE_PREFIX"`" + fi + RESOLVE_PREFIX="`dirname "$RESOLVE_PREFIX"`" + else + dnl Bail out, keep latest answer + break + fi + LVL="`expr $LVL + 1`" + done + + if test -n "$RESOLVE_SUFFIX" ; then + if test x"$RESOLVE_PREFIX" = x ; then + RESOLVE_PREFIX="/" + fi + if test x"$RESOLVE_PREFIX" = x/ ; then + $2="/$RESOLVE_SUFFIX" + else + $2="$RESOLVE_PREFIX/$RESOLVE_SUFFIX" + fi + else + $2="$RESOLVE_PREFIX" + fi + + unset LVL RESOLVE_PREFIX RESOLVE_SUFFIX +]) + AC_DEFUN([AX_REALPATH], [ dnl # resolve links - #1 value (not quoted by caller) @@ -93,7 +143,7 @@ AC_DEFUN([AX_REALPATH], AC_MSG_WARN([Path name '$PRG' not resolved (absent or access to ancestor directories denied)]) RESOLVE_ERROR=1 ], [ - AX_REALPATH_SHELL_RECURSIVE([$1], [REALPRG], [0]) + AX_REALPATH_SHELL_RECURSIVE([$1], [REALPRG]) ]) ]) From 2ac15a7cc5a38ccb38615c2f6e200ab36e1706d8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:04:32 +0100 Subject: [PATCH 0500/1232] m4/ax_realpath.m4: AX_REALPATH_SHELL_RECURSIVE() AX_REALPATH_SHELL_ONELEVEL(): drop support for LVL (shell vars misbehave here so not interesting) [#1859] --- m4/ax_realpath.m4 | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 40d42ef04b..dfd7684292 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -11,49 +11,47 @@ AC_DEFUN([AX_REALPATH_SHELL_ONELEVEL], [ dnl # resolve links - #1 value (not quoted by caller) or some its dnl # ancestor directory may be a symlink; save into varname #2. - dnl # In case of problems return #1 and set non-zero RESOLVE_ERROR - dnl # Recursion depth in #3 impacts local variable naming - dnl # to recurse backwards from original name to root "/" + dnl # In case of problems return #1 and set non-zero RESOLVE_ERROR. + dnl # We recurse backwards from original name to root "/" dnl # (or abort mid-way). AS_IF([test x"$1" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg1)])]) AS_IF([test x"$2" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg2)])]) - AS_IF([test x"$3" = x], [AC_MSG_ERROR([Bad call to REALPATH_SHELL_ONELEVEL macro (arg3)])]) AS_IF([test x"$RESOLVE_ERROR" = x], [RESOLVE_ERROR=0]) AS_IF([test x"$RESOLVE_ERROR" != x0 || test x"$1" = x/], [dnl Quick bail out $2="$1" ], [ dnl # Code below was adapted from Apache Tomcat startup.sh - TGT$3="$1" + TGT="$1" - while test -h "$TGT$3" ; do - LS_OUT="`ls -ld "$TGT$3"`" || { RESOLVE_ERROR=$? ; break ; } + while test -h "$TGT" ; do + LS_OUT="`ls -ld "$TGT"`" || { RESOLVE_ERROR=$? ; break ; } LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } if expr "$LINK" : '/.*' > /dev/null; then - TGT$3="$LINK" + TGT="$LINK" else - TGT$3="`dirname "$TGT$3"`/$LINK" + TGT="`dirname "$TGT"`/$LINK" fi done if test "$RESOLVE_ERROR" = 0 ; then - TGTDIR$3="`dirname "$TGT$3"`" && \ - TGTDIR$3="`cd "$TGTDIR$3" && pwd`" || { - TGTDIR$3="`dirname "$TGT$3"`" || \ + TGTDIR="`dirname "$TGT"`" && \ + TGTDIR="`cd "$TGTDIR" && pwd`" || { + TGTDIR="`dirname "$TGT"`" || \ RESOLVE_ERROR=$? ; } if test "$RESOLVE_ERROR" = 0 ; then - while test -h "$TGTDIR$3" ; do - LS_OUT="`ls -ld "$TGTDIR$3"`" || { RESOLVE_ERROR=$? ; break ; } + while test -h "$TGTDIR" ; do + LS_OUT="`ls -ld "$TGTDIR"`" || { RESOLVE_ERROR=$? ; break ; } LINK="`expr "$LS_OUT" : '.*-> \(.*\)$'`" || { RESOLVE_ERROR=$? ; break ; } if expr "$LINK" : '/.*' > /dev/null; then - TGTDIR$3="$LINK" + TGTDIR="$LINK" else - PARENTDIR$3="`dirname "$TGTDIR$3"`" - case "$PARENTDIR$3" in - /) TGTDIR$3="/$LINK" ; break ;; - *) TGTDIR$3="$PARENTDIR$3/$LINK" ;; + PARENTDIR="`dirname "$TGTDIR"`" + case "$PARENTDIR" in + /) TGTDIR="/$LINK" ; break ;; + *) TGTDIR="$PARENTDIR/$LINK" ;; esac fi done @@ -61,12 +59,12 @@ AC_DEFUN([AX_REALPATH_SHELL_ONELEVEL], fi if test "$RESOLVE_ERROR" = 0 ; then - $2="$TGTDIR$3/`basename "$TGT$3"`" + $2="$TGTDIR/`basename "$TGT"`" else $2="$1" fi - unset TGT$3 TGTDIR$3 PARENTDIR$3 + unset TGT TGTDIR PARENTDIR unset LS_OUT LINK ]) ]) @@ -78,7 +76,6 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], dnl helper method above and will abort the script upon problems. dnl The RESOLVE_ERROR is provided and unset by caller. - LVL=0 RESOLVE_PREFIX="$1" RESOLVE_SUFFIX="" @@ -89,7 +86,7 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], ; do dnl In case of non-fatal resolve error, value in RESOLVE_PREFIX dnl should remain unchanged, and a RESOLVE_ERROR flag raised. - AX_REALPATH_SHELL_ONELEVEL([$RESOLVE_PREFIX], [RESOLVE_PREFIX], [0]) + AX_REALPATH_SHELL_ONELEVEL([$RESOLVE_PREFIX], [RESOLVE_PREFIX]) if test x"$RESOLVE_ERROR" = x0 ; then dnl Recurse to check the (grand)parent dir (if any) if test -n "$RESOLVE_SUFFIX" ; then @@ -102,7 +99,6 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], dnl Bail out, keep latest answer break fi - LVL="`expr $LVL + 1`" done if test -n "$RESOLVE_SUFFIX" ; then @@ -118,7 +114,7 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], $2="$RESOLVE_PREFIX" fi - unset LVL RESOLVE_PREFIX RESOLVE_SUFFIX + unset RESOLVE_PREFIX RESOLVE_SUFFIX ]) AC_DEFUN([AX_REALPATH], From 176ba7babe4f0ad229df8530c2864a89535de9fb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:24:59 +0100 Subject: [PATCH 0501/1232] m4/ax_realpath.m4: AX_REALPATH(): try AX_REALPATH_SHELL_RECURSIVE even if file is not found initially; fix how we decide it is not found [#1859] --- m4/ax_realpath.m4 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index dfd7684292..cefa94b738 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -135,12 +135,15 @@ AC_DEFUN([AX_REALPATH], AS_IF([test -z "$REALPRG"], [ RESOLVE_ERROR=0 - AS_IF([test -e "$PRG"], [ - AC_MSG_WARN([Path name '$PRG' not resolved (absent or access to ancestor directories denied)]) - RESOLVE_ERROR=1 - ], [ - AX_REALPATH_SHELL_RECURSIVE([$1], [REALPRG]) + dnl Note: not all "test" implementations have "-e", so got fallbacks: + AS_IF([test -e "$1" || test -f "$1" || test -s "$1" || test -d "$1" || test -L "$1" || test -h "$1" || test -c "$1" || test -b "$1" || test -p "$1"], + [], [ + AC_MSG_WARN([Path name '$1' not found (absent or access to ancestor directories denied)]) + dnl We can still try to resolve, e.g. to find + dnl the real location an absent file would be in + dnl RESOLVE_ERROR=1 ]) + AX_REALPATH_SHELL_RECURSIVE([$1], [REALPRG]) ]) AS_IF([test -n "$REALPRG"], [ From c372d357c240e7a97d3edd4cf99e5eaa775c6817 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:32:38 +0100 Subject: [PATCH 0502/1232] m4/ax_realpath.m4: AX_REALPATH(): report if resolved pathname differs from input value [#1859] --- m4/ax_realpath.m4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index cefa94b738..e72618f11c 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -147,7 +147,10 @@ AC_DEFUN([AX_REALPATH], ]) AS_IF([test -n "$REALPRG"], [ - AC_MSG_RESULT([$REALPRG]) + AS_IF([test x"$REALPRG" = x"$1"], + [AC_MSG_RESULT([$REALPRG])], + [AC_MSG_RESULT([$REALPRG (differs from input)])] + ) $2="$REALPRG" ], [ dnl Indent due to newline from warning and/or tool errors above From 7bd4f3ccfa1dda1c52932a44b53b8807cf5d5a3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:40:39 +0100 Subject: [PATCH 0503/1232] m4/ax_realpath.m4: AX_REALPATH(): quote reported pathnames consistently [#1859] --- m4/ax_realpath.m4 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index e72618f11c..24792f1997 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -148,13 +148,13 @@ AC_DEFUN([AX_REALPATH], AS_IF([test -n "$REALPRG"], [ AS_IF([test x"$REALPRG" = x"$1"], - [AC_MSG_RESULT([$REALPRG])], - [AC_MSG_RESULT([$REALPRG (differs from input)])] + [AC_MSG_RESULT(['$REALPRG'])], + [AC_MSG_RESULT(['$REALPRG' (differs from input)])] ) $2="$REALPRG" ], [ dnl Indent due to newline from warning and/or tool errors above - AC_MSG_RESULT([...failed to resolve, keeping original: $1]) + AC_MSG_RESULT([...failed to resolve, keeping original: '$1']) $2="$1" ]) @@ -164,7 +164,7 @@ AC_DEFUN([AX_REALPATH], AC_DEFUN([UNITTEST_AX_REALPATH_EXPECT], [ AX_REALPATH([$1], [TMPNAME]) - AS_IF([test x"$TMPNAME" != x"$2"], [AC_MSG_WARN([>>> Got: $TMPNAME (should be $2)])]) + AS_IF([test x"$TMPNAME" != x"$2"], [AC_MSG_WARN([>>> Got: '$TMPNAME' (should be '$2')])]) ]) AC_DEFUN([UNITTEST_AX_REALPATH], @@ -190,11 +190,11 @@ AC_DEFUN([UNITTEST_AX_REALPATH], AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([=== Should be a shell interpreter here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/exe], [TMPNAME]) - AC_MSG_NOTICE([>>> Got: $TMPNAME]) + AC_MSG_NOTICE([>>> Got: '$TMPNAME']) AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([=== Should be an stdin socket here (if procfs is supported on the platform)]) AX_REALPATH([/proc/$$/fd/1], [TMPNAME]) - AC_MSG_NOTICE([>>> Got: $TMPNAME]) + AC_MSG_NOTICE([>>> Got: '$TMPNAME']) AC_MSG_NOTICE([=======]) AC_MSG_NOTICE([=== Should not have access to next SYMLINK (reading link content is forbidden, if procfs is supported on the platform and if not root)]) UNITTEST_AX_REALPATH_EXPECT([/proc/1/exe], [/proc/1/exe]) From 34d614c5e9dbd5fec8b8081d74081f5c54421883 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:42:07 +0100 Subject: [PATCH 0504/1232] configure.ac: disable UNITTEST_AX_REALPATH and the exit afterwards [#1859] --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7a0d196bcd..ce9d817274 100644 --- a/configure.ac +++ b/configure.ac @@ -141,8 +141,8 @@ dnl Note: for practical and platform-independent use, see AX_REALPATH macro AC_CHECK_PROGS([REALPATH], [realpath], []) dnl FIXME: remove after dev-testing -UNITTEST_AX_REALPATH -exit +dnl UNITTEST_AX_REALPATH +dnl exit dnl NOTE: for definition of NUT_* autoconf macros, see m4/ directory dnl and docs/macros.txt From 31aa0b669fafa960b5cfeab9af9e5967a5dfd1e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 16:48:40 +0100 Subject: [PATCH 0505/1232] m4/ax_realpath.m4: comment about recursion involved [#1859] --- m4/ax_realpath.m4 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/m4/ax_realpath.m4 b/m4/ax_realpath.m4 index 24792f1997..6b8cdbc642 100644 --- a/m4/ax_realpath.m4 +++ b/m4/ax_realpath.m4 @@ -86,6 +86,9 @@ AC_DEFUN([AX_REALPATH_SHELL_RECURSIVE], ; do dnl In case of non-fatal resolve error, value in RESOLVE_PREFIX dnl should remain unchanged, and a RESOLVE_ERROR flag raised. + dnl Note that the recursion would technically re-check the last + dnl seen object (the parent directory), but should quickly move + dnl on since it is not a symlink anymore. So not too ineffecient. AX_REALPATH_SHELL_ONELEVEL([$RESOLVE_PREFIX], [RESOLVE_PREFIX]) if test x"$RESOLVE_ERROR" = x0 ; then dnl Recurse to check the (grand)parent dir (if any) From e8227be506967a98eab6a2fdd205ba2263d6db54 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 20:52:04 +0100 Subject: [PATCH 0506/1232] Revert "clients/upssched.c: main(): find use for argc" This reverts commit dca2315fa8fb9a80528726cbc235310f19aa948f. Not needed anymore, and actually added a bug (prog not remembered). --- clients/upssched.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index b38b84f0a2..73dff7485e 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1326,15 +1326,9 @@ static void checkconf(void) int main(int argc, char **argv) { - const char *prog = NULL; - /* More a use for argc to avoid warnings than a real need: */ - if (argc > 0) { - xbasename(argv[0]); - } else { - xbasename("upssched"); - } + const char *prog = xbasename(argv[0]); - verbose = 1; /* TODO: remove when done testing, or add -D */ + verbose = 1; /* TODO: remove when done testing */ /* normally we don't have stderr, so get this going to syslog early */ open_syslog(prog); From 901147097c0d151e134b1085e6cb258239c0da3b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 21:04:33 +0100 Subject: [PATCH 0507/1232] clients/upssched.c: enable command-line argument handling [#1863] Closes: #1863 --- clients/upssched.c | 56 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index 73dff7485e..fc37052201 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -68,7 +68,6 @@ typedef struct ttype_s { static ttype_t *thead = NULL; static conn_t *connhead = NULL; static char *cmdscript = NULL, *pipefn = NULL, *lockfn = NULL; -static int verbose = 0; /* use for debugging */ /* ups name and notify type (string) as received from upsmon */ static const char *upsname, *notify_type; @@ -163,7 +162,7 @@ static void checktimers(void) if (emptyctr < EMPTY_WAIT) return; - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Timer queue empty, exiting"); #ifdef UPSSCHED_RACE_TEST @@ -185,7 +184,7 @@ static void checktimers(void) tmpnext = tmp->next; if (now >= tmp->etime) { - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Event: %s ", tmp->name); exec_cmd(tmp->name); @@ -215,7 +214,7 @@ static void start_timer(const char *name, const char *ofsstr) return; } - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "New timer: %s (%ld seconds)", name, ofs); /* now add to the queue */ @@ -243,7 +242,7 @@ static void cancel_timer(const char *name, const char *cname) for (tmp = thead; tmp != NULL; tmp = tmp->next) { if (!strcmp(tmp->name, name)) { /* match */ - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Cancelling timer: %s", name); removetimer(tmp); return; @@ -252,7 +251,7 @@ static void cancel_timer(const char *name, const char *cname) /* this is not necessarily an error */ if (cname && cname[0]) { - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Cancel %s, event: %s", name, cname); exec_cmd(cname); @@ -779,7 +778,7 @@ static void start_daemon(TYPE_FD lockfd) pipefd = open_sock(); - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Timer daemon started"); /* release the parent */ @@ -851,7 +850,7 @@ static void start_daemon(TYPE_FD lockfd) } pipefd = open_sock(); - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Timer daemon started"); /* drop the lock now that the background is running */ @@ -1217,7 +1216,7 @@ static void parse_at(const char *ntype, const char *un, const char *cmd, return; } - if (verbose) + if (nut_debug_level) upslogx(LOG_INFO, "Executing command: %s", ca1); exec_cmd(ca1); @@ -1324,11 +1323,48 @@ static void checkconf(void) pconf_finish(&ctx); } +static void help(const char *arg_progname) + __attribute__((noreturn)); + +static void help(const char *arg_progname) +{ + printf("upssched: upsmon's scheduling helper for offset timers\n"); + printf("Practical behavior is managed by UPSNAME and NOTIFYTYPE envvars\n"); + + printf("\nUsage: %s [OPTIONS]\n\n", arg_progname); + printf(" -D raise debugging level (and stay foreground by default)\n"); + printf(" -V display the version of this software\n"); + printf(" -h display this help\n"); + + nut_report_config_flags(); + + exit(EXIT_SUCCESS); +} + + int main(int argc, char **argv) { const char *prog = xbasename(argv[0]); + int i; + + while ((i = getopt(argc, argv, "+DVh")) != -1) { + switch (i) { + case 'D': + nut_debug_level++; + break; + + case 'h': + help(argv[0]); +#ifndef HAVE___ATTRIBUTE__NORETURN + break; +#endif - verbose = 1; /* TODO: remove when done testing */ + case 'V': + /* just show the optional CONFIG_FLAGS banner */ + nut_report_config_flags(); + exit(EXIT_SUCCESS); + } + } /* normally we don't have stderr, so get this going to syslog early */ open_syslog(prog); From 75a9208fc014d8867f22febd043e10acc1e0632f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 21:17:05 +0100 Subject: [PATCH 0508/1232] Fix help()/usage() in many programs to suggest "-h" and/or "-V" options --- clients/upsc.c | 4 ++++ clients/upscmd.c | 1 + clients/upslog.c | 2 ++ clients/upsmon.c | 1 + clients/upsrw.c | 1 + server/upsd.c | 4 ++-- tools/nut-scanner/nut-scanner.c | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clients/upsc.c b/clients/upsc.c index 5cc2a4d8cc..4a01682b9f 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -57,6 +57,10 @@ static void usage(const char *prog) printf(" -c - lists each client connected on , one per line.\n"); printf(" - upsd server, [@[:]] form\n"); + printf("\nCommon arguments:\n"); + printf(" -V - display the version of this software\n"); + printf(" -h - display this help text\n"); + nut_report_config_flags(); } diff --git a/clients/upscmd.c b/clients/upscmd.c index a5223baa57..4d71ebce2f 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -54,6 +54,7 @@ static void usage(const char *prog) printf("Administration program to initiate instant commands on UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); + printf(" -V display the version of this software\n"); printf(" -l show available commands on UPS \n"); printf(" -u set username for command authentication\n"); printf(" -p set password for command authentication\n"); diff --git a/clients/upslog.c b/clients/upslog.c index b18be40714..f2a8cd95c6 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -161,6 +161,8 @@ static void help(const char *prog) printf(" -m - Monitor UPS \n"); printf(" - Example: -m myups@server,/var/log/myups.log\n"); printf(" -u - Switch to if started as root\n"); + printf(" -V - Display the version of this software\n"); + printf(" -h - Display this help text\n"); printf("\n"); printf("Some valid format string escapes:\n"); diff --git a/clients/upsmon.c b/clients/upsmon.c index b959c42ebf..e827bc2020 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2175,6 +2175,7 @@ static void help(const char *arg_progname) printf(" -D raise debugging level (and stay foreground by default)\n"); printf(" -F stay foregrounded even if no debugging is enabled\n"); printf(" -B stay backgrounded even if debugging is bumped\n"); + printf(" -V display the version of this software\n"); printf(" -h display this help\n"); printf(" -K checks POWERDOWNFLAG, sets exit code to 0 if set\n"); printf(" -p always run privileged (disable privileged parent)\n"); diff --git a/clients/upsrw.c b/clients/upsrw.c index 229237225e..2086d6de43 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -53,6 +53,7 @@ static void usage(const char *prog) printf("Demo program to set variables within UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); + printf(" -V display the version of this software\n"); printf(" -s specify variable to be changed\n"); printf(" use -s VAR=VALUE to avoid prompting for value\n"); printf(" -l show all possible read/write variables.\n"); diff --git a/server/upsd.c b/server/upsd.c index 847d8ff398..b49bdd28d6 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1499,11 +1499,11 @@ static void help(const char *arg_progname) printf(" -F stay foregrounded even if no debugging is enabled\n"); printf(" -FF stay foregrounded and still save the PID file\n"); printf(" -B stay backgrounded even if debugging is bumped\n"); - printf(" -h display this help\n"); + printf(" -h display this help text\n"); + printf(" -V display the version of this software\n"); printf(" -r chroots to \n"); printf(" -q raise log level threshold\n"); printf(" -u switch to (if started as root)\n"); - printf(" -V display the version of this software\n"); printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 345fe4bd99..8a20f1a38e 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -337,6 +337,7 @@ static void show_usage() printf(" -N, --disp_nut_conf: Display result in the ups.conf format\n"); printf(" -P, --disp_parsable: Display result in a parsable format\n"); printf("\nMiscellaneous options:\n"); + printf(" -h, --help: display this help text\n"); printf(" -V, --version: Display NUT version\n"); printf(" -a, --available: Display available bus that can be scanned\n"); printf(" -q, --quiet: Display only scan result. No information on currently scanned bus is displayed.\n"); From 3ecca8da5d0f418ed34bfdd33ddced9da211147d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 21:17:54 +0100 Subject: [PATCH 0509/1232] clients/upssched.c: parse_at(): add upsdebugx() tracing [#1858] --- clients/upssched.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index fc37052201..e597694b2f 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1190,27 +1190,50 @@ static void parse_at(const char *ntype, const char *un, const char *cmd, } /* check upsname: does this apply to us? */ - if (strcmp(upsname, un) != 0) - if (strcmp(un, "*") != 0) + upsdebugx(2, "%s: is '%s' in AT command the '%s' we were launched to process?", + __func__, un, upsname); + if (strcmp(upsname, un) != 0) { + if (strcmp(un, "*") != 0) { + upsdebugx(1, "%s: SKIP: '%s' in AT command " + "did not match the '%s' UPSNAME " + "we were launched to process", + __func__, un, upsname); return; /* not for us, and not the wildcard */ + } else { + upsdebugx(1, "%s: this AT command is for a wildcard: matched", __func__); + } + } else { + upsdebugx(1, "%s: '%s' in AT command matched the '%s' " + "UPSNAME we were launched to process", + __func__, un, upsname); + } /* see if the current notify type matches the one from the .conf */ - if (strcasecmp(notify_type, ntype) != 0) + if (strcasecmp(notify_type, ntype) != 0) { + upsdebugx(1, "%s: SKIP: '%s' in AT command " + "did not match the '%s' NOTIFYTYPE " + "we were launched to process", + __func__, ntype, notify_type); return; + } /* if command is valid, send it to the daemon (which may start it) */ if (!strcmp(cmd, "START-TIMER")) { + upsdebugx(1, "%s: processing %s", __func__, cmd); sendcmd("START", ca1, ca2); return; } if (!strcmp(cmd, "CANCEL-TIMER")) { + upsdebugx(1, "%s: processing %s", __func__, cmd); sendcmd("CANCEL", ca1, ca2); return; } if (!strcmp(cmd, "EXECUTE")) { + upsdebugx(1, "%s: processing %s", __func__, cmd); + if (ca1[0] == '\0') { upslogx(LOG_ERR, "Empty EXECUTE command argument"); return; From b73921e78a131594499b3ff2bd941ed1d8d273b2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Feb 2023 21:24:11 +0100 Subject: [PATCH 0510/1232] docs/developers.txt: update coding style guide about braces after if/while/for/... even for a single line --- docs/developers.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/developers.txt b/docs/developers.txt index fde3935a39..e0f5802e48 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -542,6 +542,12 @@ if (condition) { } ------------------------------------------------------------------------------- +NOTE: Earlier revisions of coding style might suggest avoiding braces if just +one line is added as condition/loop/etc. handling code. Current approach is to +welcome them even for single lines: on one hand, this confirms the intention +that only this line is the conditional code; on another, this minimizes the +context differences for later code comparisons, relocation, refactoring, etc. + Un-used variables and function arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 6e7c58b731009c0379f281c0834f400825c61415 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Mar 2023 09:47:33 +0100 Subject: [PATCH 0511/1232] configure.ac: comment that in some systems, the upsd in PATH is a shell wrapper [#1859] e.g. in Debian packaging where it is tied into "MODE" of nut.conf --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index ce9d817274..0c4ff50121 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,8 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ DEPLOYED_BINDIR="${PREFIX_BINDIR}" dnl Note use of AC_PATH_PROG for specific pathname (not AC_CHECK_PROGS which picks filename variants)! dnl Note: "ordinary" users might not have "sbin" in their default PATH, so appending it: + dnl Note: in some systems, the file in PATH is a shell + dnl wrapper for /etc/nut/nut.conf MODE support AC_PATH_PROG([DEPLOYED_UPSD], [upsd], [], [${PREFIX_SBINDIR}:${PATH}:/sbin:/usr/sbin:/usr/local/sbin]) dnl ...however "upsc" is a userland tool so should be there: AC_PATH_PROG([DEPLOYED_UPSC], [upsc], [], [${PREFIX_BINDIR}:${PATH}]) From d9fabea41e11f821232a216eb2477b7c410feb3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Mar 2023 09:50:33 +0100 Subject: [PATCH 0512/1232] configure.ac: fix re-entry of the script when handling --enable-inplace-runtime [#1859] --- configure.ac | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0c4ff50121..489123e0a6 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,7 @@ dnl so unspecified options are not necessarily at default values for this script F="" AS_CASE(["${_flag_enable_inplace_runtime}"], [no], [ dnl Explicitly disabled... did we re-enter? Save the value to be seen: - AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x], [ + AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x && test x"${NUT_VERSION_DEPLOYED-}" != x""], [ F="--enable-inplace-runtime='${NUT_VERSION_DEPLOYED}'" ]) ], @@ -313,8 +313,10 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) AS_IF([test x"${NUT_VERSION_DEPLOYED}" != x], [ AC_MSG_NOTICE([NUT_VERSION_DEPLOYED: ${NUT_VERSION_DEPLOYED}]) - export NUT_VERSION_DEPLOYED + ],[ + NUT_VERSION_DEPLOYED="" ]) + export NUT_VERSION_DEPLOYED eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime ],[ AC_MSG_RESULT([not reported]) From 1e790b44dc78673948740e9288a1e47e3b41c95f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Mar 2023 11:36:02 +0100 Subject: [PATCH 0513/1232] configure.ac: reshuffle for --enable-inplace-runtime=reenter support; detect sysconfdir/user/group in one place where we care for "inplace" mode [#1859] --- configure.ac | 287 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 190 insertions(+), 97 deletions(-) diff --git a/configure.ac b/configure.ac index 489123e0a6..7be3e97ec7 100644 --- a/configure.ac +++ b/configure.ac @@ -46,15 +46,16 @@ for F in "$@" ; do done dnl Keep it "known" that we tried to re-use at least some local configuration dnl so unspecified options are not necessarily at default values for this script +AS_IF([test x"${NUT_VERSION_DEPLOYED-}" = x""], [_flag_enable_inplace_runtime="reenter"]) F="" -AS_CASE(["${_flag_enable_inplace_runtime}"], - [no], [ dnl Explicitly disabled... did we re-enter? Save the value to be seen: - AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x && test x"${NUT_VERSION_DEPLOYED-}" != x""], [ - F="--enable-inplace-runtime='${NUT_VERSION_DEPLOYED}'" - ]) - ], - [""], [], - [F="${_flag_enable_inplace_runtime}"]) +AS_IF([test x"${NUT_VERSION_DEPLOYED-}" != x && test x"${NUT_VERSION_DEPLOYED-}" != x""], [ + dnl Even if explicitly disabled... did we re-enter? Save the value to be seen: + F="--enable-inplace-runtime='${NUT_VERSION_DEPLOYED}'" + ],[ + AS_CASE(["${_flag_enable_inplace_runtime}"], + [no|""|reenter], [], + [F="${_flag_enable_inplace_runtime}"]) + ]) AS_IF([test x"$F" != x], [ test -z "${CONFIG_FLAGS}" \ && CONFIG_FLAGS="$F" \ @@ -152,6 +153,23 @@ dnl | default values for things later on (can be overridden) | STATEPATH="/var/state/ups" +dnl Historically this refers to *system location* for PID files, +dnl and more specifically that for `upsmon` (running as `root`). +dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below +dnl for the unprivileged daemons (`upsd`, drivers). +PIDPATH="/var/run" +dnl Honour new LFS recommendations if applied on the build system: +AS_IF([test -d "/run"], [PIDPATH="/run"]) + +dnl Defaults for respective configure options below +dnl Note these defaults may change further below depending on OS and +dnl certain other configure options (e.g. "in-place replacement") +RUN_AS_USER="nobody" +RUN_AS_GROUP="nobody" +AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GROUP}"`"], + [RUN_AS_GROUP="nogroup"] +) + dnl NOTE: NUT legacy default, keep as is for least surprise dnl Distributions are however welcome to specify the option to use tmpfs AS_CASE([${target_os}], @@ -219,7 +237,8 @@ NUT_ARG_ENABLE([inplace-runtime], [Request configure option defaults for runtime user/group/confpath based on currently installed NUT (to extent these can be detected)], [no]) -AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ +dnl Check for not re-entering in this run - whether NUT_VERSION_DEPLOYED is set +AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${NUT_VERSION_DEPLOYED-}" = x], [ AC_MSG_NOTICE([checking for location, CONFIG_FLAGS and version of an already deployed NUT build (if it reports those)]) dnl If existing NUT installation reports its build options, re-run this @@ -284,6 +303,12 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}${NUT_VERSION_DEPLOYED}" = x], [], [break]) done + AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ + AC_MSG_RESULT([CONFIG_FLAGS_DEPLOYED: ${CONFIG_FLAGS_DEPLOYED}]) + ],[ + AC_MSG_RESULT([CONFIG_FLAGS_DEPLOYED: not reported]) + ]) + dnl Account for custom paths if known/found: AS_IF([test x"${DEPLOYED_PREFIX}" != x && test x"${DEPLOYED_PREFIX}" != x"${prefix}"], AC_MSG_WARN([Deployed NUT installation uses a PREFIX different from one specified (wins) or derived (loses) for this build: '${DEPLOYED_PREFIX}' vs. '${prefix}']) @@ -306,39 +331,23 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${sbindir}" != x], [ [CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --bindir='${DEPLOYED_BINDIR}'"]) ]) - AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ - AC_MSG_RESULT([${CONFIG_FLAGS_DEPLOYED}]) - AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) - dnl For multiply-specified flags with conflicting values, last mention wins: - AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) - AS_IF([test x"${NUT_VERSION_DEPLOYED}" != x], [ - AC_MSG_NOTICE([NUT_VERSION_DEPLOYED: ${NUT_VERSION_DEPLOYED}]) - ],[ - NUT_VERSION_DEPLOYED="" - ]) - export NUT_VERSION_DEPLOYED - eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime - ],[ - AC_MSG_RESULT([not reported]) - ]) -]) - -dnl Defaults for respective configure options below -dnl Note these defaults may change further below depending on OS and -dnl certain other configure options (e.g. "in-place replacement") -RUN_AS_USER="nobody" -RUN_AS_GROUP="nobody" -AS_IF([test -n "`getent group nogroup`" && ! test -n "`getent group "${RUN_AS_GROUP}"`"], - [RUN_AS_GROUP="nogroup"] -) + AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--sysconfdir=*], [ + for F in ${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS} ; do + case "$F" in + "--sysconfdir="*) sysconfdir="`echo "$F" | ( IFS='=' read K V ; echo "$V" )`" ;; + esac + done + ], + [ + dnl If there was no custom --sysconfdir=/etc/myNUT passed, + dnl try to default it to something from existing deployment. + dnl NOTE: Single-quotes are correct for autotools default, + dnl expanded at runtime (see conftemp tricks below) -AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ - dnl If there was no custom --sysconfdir=/etc/myNUT passed, - dnl try to default it to something from existing deployment. - dnl NOTE: Single-quotes are correct for autotools default, - dnl expanded at runtime (see conftemp tricks below) - AS_IF([test x'${prefix}/etc' = x"${sysconfdir}"], [ AC_MSG_CHECKING([for in-place replacement default sysconfdir (better than '${sysconfdir}')]) + DEPLOYED_SYSCONFDIR="" + dnl TODO: Any more reasonable defaults? Pile them on here :) for D in \ /etc/nut /etc/ups \ @@ -349,28 +358,158 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ if test -e "$D/ups.conf" || test -e "$D/upsmon.conf" \ || ( test -e "$D/upsd.conf" && test -e "$D/upsd.users" ) \ ; then - sysconfdir="$D" + DEPLOYED_SYSCONFDIR="$D" break else if test -d "$D/" && test ! -r "$D/" ; then dnl Keeping order of preference defined by "for" loop: AC_MSG_WARN([Picking directory '${D}' which exists but current build user may not read]) - sysconfdir="$D" + DEPLOYED_SYSCONFDIR="$D" break fi fi done - AC_MSG_RESULT([${sysconfdir}]) + + AS_IF([test -n "${DEPLOYED_SYSCONFDIR}"], [ + AC_MSG_RESULT([${DEPLOYED_SYSCONFDIR}]) + dnl May be used in searches below: + sysconfdir="${DEPLOYED_SYSCONFDIR}" + CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --sysconfdir='${DEPLOYED_SYSCONFDIR}'" + ], [ + AC_MSG_RESULT([not detected]) ]) -]) + ]) -dnl Historically this refers to *system location* for PID files, -dnl and more specifically that for `upsmon` (running as `root`). -dnl See also ALTPIDPATH (defaulted to STATEPATH) setting below -dnl for the unprivileged daemons (`upsd`, drivers). -PIDPATH="/var/run" -dnl Honour new LFS recommendations if applied on the build system: -AS_IF([test -d "/run"], [PIDPATH="/run"]) + dnl Prepare paths that may be used in user/group searches below: + conftemp="${sysconfdir}" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + CONFPATH="${conftemp}" + + AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--libdir=*], [ + for F in ${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS} ; do + case "$F" in + "--libdir="*) libdir="`echo "$F" | ( IFS='=' read K V ; echo "$V" )`" ;; + esac + done + ] + ) + + conftemp="${libdir}" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + LIBDIR="${conftemp}" + + AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--with-pkgconfig-dir=*], [ + for F in ${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS} ; do + case "$F" in + "--with-pkgconfig-dir="*) pkgconfigdir="`echo "$F" | ( IFS='=' read K V ; echo "$V" )`" ;; + esac + done + ] + ) + + dnl pkgconfigdir may have more indirections: + conftemp="${pkgconfigdir}" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + eval conftemp=\"${conftemp}\" + PKGCONFIGDIR="${conftemp}" + + AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--with-group=*], [], + [ + AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) + nut_inplace_group="" + AS_IF([test -d "${udevdir}/rules.d"], + [for F in "${udevdir}/rules.d"/*-nut-*.rules ; do + if test -s "$F" ; then + nut_inplace_group="`grep GROUP= "$F" | head -1 | sed 's,^.* GROUP="*\(.*\)"*.*$,\1,'`" \ + && test -n "`getent group "${nut_inplace_group}"`" \ + && AC_MSG_RESULT([Got from ${F}]) \ + && break \ + || nut_inplace_group="" + fi + done + ]) + + AS_IF([test -z "${nut_inplace_group}"], + [AS_IF([test -n "`getent group nut`"], [nut_inplace_group="nut"], + [AS_IF([test -n "`getent group ups`"], [nut_inplace_group="ups"])])]) + + AS_IF([test -n "${nut_inplace_group}"], [ + AC_MSG_RESULT([${nut_inplace_group}]) + CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --with-group='${nut_inplace_group}'" + ], [ + AC_MSG_RESULT([not detected]) + ]) + ]) + + AS_CASE(["${CONFIG_FLAGS_DEPLOYED} ${CONFIG_FLAGS}"], + [*--with-user=*], [], + [ + AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) + nut_inplace_user="" + + AS_IF([test -s "${CONFPATH}/upsmon.conf"], + [for nut_inplace_user in `grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`; do \ + test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ + || nut_inplace_user="" + done + ]) + + dnl Note: with default short inplace and no prefix, this would look under + dnl /usr/local/ups/lib/pkgconfig which may be irrelevant for packaged setups + + dnl TODO: Any more reasonable defaults? Pile them on here :) + for F in \ + "${PKGCONFDIR}/libupsclient.pc" \ + "${PKGCONFDIR}/libnutclient.pc" \ + "${LIBDIR}/pkgconfig/libupsclient.pc" \ + "${LIBDIR}/pkgconfig/libnutclient.pc" \ + ; do + AS_IF([test -z "${nut_inplace_user}" && test -s "$F"], + [nut_inplace_user="`grep -E '^ *nutuser=' "$F" | sed 's,^ *nutuser=,,'`" \ + && test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from $F]) \ + || nut_inplace_user="" + ]) + done + + AS_IF([test -z "${nut_inplace_user}"], + [AS_IF([test -n "`getent passwd nut`"], [nut_inplace_user="nut"], + [AS_IF([test -n "`getent passwd ups`"], [nut_inplace_user="ups"])])]) + + AS_IF([test -n "${nut_inplace_user}"], [ + AC_MSG_RESULT([${nut_inplace_user}]) + CONFIG_FLAGS_DEPLOYED="${CONFIG_FLAGS_DEPLOYED} --with-user='${nut_inplace_user}'" + ], [ + AC_MSG_RESULT([not detected]) + ]) + ]) + + AS_IF([test x"${CONFIG_FLAGS_DEPLOYED}" != x], [ + AC_MSG_NOTICE([Detected CONFIG_FLAGS of an already deployed NUT installation, using them for --inplace-runtime configuration (restarting script)]) + dnl For multiply-specified flags with conflicting values, last mention wins: + AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime]) + AS_IF([test x"${NUT_VERSION_DEPLOYED}" != x], [ + AC_MSG_NOTICE([NUT_VERSION_DEPLOYED: ${NUT_VERSION_DEPLOYED}]) + ],[ + NUT_VERSION_DEPLOYED="" + ]) + export NUT_VERSION_DEPLOYED + eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime + ],[ + AC_MSG_NOTICE([No CONFIG_FLAGS were reported or discovered from existing NUT deployment (if any); restarting script for a clean run]) + NUT_VERSION_DEPLOYED="" + export NUT_VERSION_DEPLOYED + AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS --disable-inplace-runtime]) + eval exec "$0" $CONFIG_FLAGS --disable-inplace-runtime + ]) +]) dnl Define directory where LIBOBJS replacement functions are AC_CONFIG_LIBOBJ_DIR([common]) @@ -3528,52 +3667,6 @@ dnl ---------------------------------------------------------------------- dnl Check the user and group to run as last, so we can use the paths configured dnl above as data sources for default values if building an in-place replacement -AS_IF([test x"$nut_enable_inplace_runtime" = xyes], [ - AC_MSG_CHECKING([for in-place replacement default group (better than '${RUN_AS_GROUP}')]) - nut_inplace_group="" - AS_IF([test -d "${udevdir}/rules.d"], - [for F in "${udevdir}/rules.d"/*-nut-*.rules ; do - if test -s "$F" ; then - nut_inplace_group="`grep GROUP= "$F" | head -1 | sed 's,^.* GROUP="*\(.*\)"*.*$,\1,'`" \ - && test -n "`getent group "${nut_inplace_group}"`" \ - && AC_MSG_RESULT([Got from ${F}]) \ - && break \ - || nut_inplace_group="" - fi - done]) - AS_IF([test -n "${nut_inplace_group}"], - [RUN_AS_GROUP="${nut_inplace_group}"], - [AS_IF([test -n "`getent group nut`"], [RUN_AS_GROUP="nut"], - [AS_IF([test -n "`getent group ups`"], [RUN_AS_GROUP="ups"])])]) - AC_MSG_RESULT([${RUN_AS_GROUP}]) - - AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) - nut_inplace_user="" - AS_IF([test -s "${CONFPATH}/upsmon.conf"], - [nut_inplace_user="`grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`" \ - && test -n "`getent passwd "${nut_inplace_user}"`" \ - && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ - || nut_inplace_user=""]) - dnl Note: with default short inplace and no prefix, this would look under - dnl /usr/local/ups/lib/pkgconfig which may be irrelevant for packaged setups - AS_IF([test -z "${nut_inplace_user}" && test -s "${LIBDIR}/pkgconfig/libupsclient.pc"], - [nut_inplace_user="`grep -E '^ *nutuser=' "${LIBDIR}/pkgconfig/libupsclient.pc" | sed 's,^ *nutuser=,,'`" \ - && test -n "`getent passwd "${nut_inplace_user}"`" \ - && AC_MSG_RESULT([Got from ${LIBDIR}/pkgconfig/libupsclient.pc]) \ - || nut_inplace_user=""]) - AS_IF([test -z "${nut_inplace_user}" && test -s "${LIBDIR}/pkgconfig/libnutclient.pc"], - [nut_inplace_user="`grep -E '^ *nutuser=' "${LIBDIR}/pkgconfig/libnutclient.pc" | sed 's,^ *nutuser=,,'`" \ - && test -n "`getent passwd "${nut_inplace_user}"`" \ - && AC_MSG_RESULT([Got from ${LIBDIR}/pkgconfig/libnutclient.pc]) \ - || nut_inplace_user=""]) - - AS_IF([test -n "${nut_inplace_user}"], - [RUN_AS_USER="${nut_inplace_user}"], - [AS_IF([test -n "`getent passwd nut`"], [RUN_AS_USER="nut"], - [AS_IF([test -n "`getent passwd ups`"], [RUN_AS_USER="ups"])])]) - AC_MSG_RESULT([${RUN_AS_USER}]) -]) - AC_MSG_CHECKING(if requested user to run as) AC_ARG_WITH(user, AS_HELP_STRING([--with-user=username], [user for programs started as root (${RUN_AS_USER})]), From ff0de8ae651d9d542ee8cb8941fb4c91b77c8ca9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Mar 2023 12:04:18 +0100 Subject: [PATCH 0514/1232] configure.ac: extend search for RUN_AS_USER in upsmon.conf [#1859] --- configure.ac | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 7be3e97ec7..7548fc0831 100644 --- a/configure.ac +++ b/configure.ac @@ -453,11 +453,30 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${NUT_VERSION_DEPLOYED-}" AC_MSG_CHECKING([for in-place replacement default user (better than '${RUN_AS_USER}')]) nut_inplace_user="" + dnl Beside currently active setting, check the built-in default sugestion AS_IF([test -s "${CONFPATH}/upsmon.conf"], - [for nut_inplace_user in `grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`; do \ - test -n "`getent passwd "${nut_inplace_user}"`" \ - && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ - || nut_inplace_user="" + [for nut_inplace_user in \ + `grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`\ + `grep -E '^ *##*RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $2}'`\ + `grep -E '^ *##* *RUN_AS_USER' "${CONFPATH}/upsmon.conf" | awk '{print $3}'`\ + ; do \ + AS_IF([test -z "${nut_inplace_user}"], [ + test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ + || nut_inplace_user=""]) + done + ]) + + AS_IF([test -s "${CONFPATH}/upsmon.conf.sample" && test -z "${nut_inplace_user}"], + [for nut_inplace_user in \ + `grep -E '^ *RUN_AS_USER' "${CONFPATH}/upsmon.conf.sample" | awk '{print $2}'`\ + `grep -E '^ *##*RUN_AS_USER' "${CONFPATH}/upsmon.conf.sample" | awk '{print $2}'`\ + `grep -E '^ *##* *RUN_AS_USER' "${CONFPATH}/upsmon.conf.sample" | awk '{print $3}'`\ + ; do \ + AS_IF([test -z "${nut_inplace_user}"], [ + test -n "`getent passwd "${nut_inplace_user}"`" \ + && AC_MSG_RESULT([Got from ${CONFPATH}/upsmon.conf]) \ + || nut_inplace_user=""]) done ]) From 8ee685f7873d5fc96abd0e7f9b04f8356f633534 Mon Sep 17 00:00:00 2001 From: modrisb Date: Wed, 1 Mar 2023 16:17:38 +0200 Subject: [PATCH 0515/1232] removed define for debug --- drivers/generic_gpio_libgpiod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index f9a65ee2cc..631c168d59 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -67,7 +67,7 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; */ -#define LOCALTEST +#undef LOCALTEST #ifdef LOCALTEST struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { NUT_UNUSED_VARIABLE(name); From 04d15274af3873a7918fc3de644c5899eea30547 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 1 Mar 2023 19:07:37 +0100 Subject: [PATCH 0516/1232] docs/scheduling.txt: align example timeouts in different paragraphs --- docs/scheduling.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/scheduling.txt b/docs/scheduling.txt index 84ba454695..a2db43e8b3 100644 --- a/docs/scheduling.txt +++ b/docs/scheduling.txt @@ -180,12 +180,12 @@ Executing commands immediately ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As an example, consider the scenario where a UPS goes onto battery power. -However, the users are not informed until 60 seconds later -- using a timer as +However, the users are not informed until 30 seconds later -- using a timer as described above. Whilst this may let the *logged in* users know that the UPS is on battery power, it does not inform any users subsequently logging in. To enable this we could, at the same time, create a file which is read and displayed to any user trying to login whilst the UPS is on battery power. If -the UPS comes back onto utility power within 60 seconds, then we can cancel +the UPS comes back onto utility power within 30 seconds, then we can cancel the timer and remove the file, as described above. However, if the UPS comes back onto utility power say 5 minutes later then we do not want to use any timers but we still want to remove the file. To do this we could use: From 5a23c8ceb44b03a38122146d902422063c1ad061 Mon Sep 17 00:00:00 2001 From: modrisb Date: Thu, 2 Mar 2023 17:55:30 +0200 Subject: [PATCH 0517/1232] removed test code and finalized styling --- drivers/generic_gpio_common.c | 23 +++++++--- drivers/generic_gpio_libgpiod.c | 74 +++++---------------------------- 2 files changed, 29 insertions(+), 68 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index eed544aad3..85df2a1767 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -28,7 +28,8 @@ struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; static struct gpioups_t *generic_gpio_open(const char *chipName); -static void get_ups_rules(struct gpioups_t *upsfd); +static void generic_gpio_close(struct gpioups_t *gpioupsfd); +static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString); static void add_rule_item(struct gpioups_t *upsfd, int newValue); static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); static int calc_rule_states(int cRules[], int subCount, int sIndex); @@ -41,7 +42,7 @@ static struct gpioups_t *generic_gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ upsfdlocal->chipName=chipName; - get_ups_rules(upsfdlocal); + get_ups_rules(upsfdlocal, (unsigned char *)getval("rules")); return upsfdlocal; } @@ -114,8 +115,7 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { /* * split subrules and translate them to array of commands/line numbers */ -static void get_ups_rules(struct gpioups_t *upsfd) { - unsigned char *rulesString = (unsigned char *)getval("rules"); +static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { /* statename=[^]line[&||[line]] */ char lexBuff[33]; int startPos = 0, endPos; @@ -124,7 +124,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { int i, j, k; int tranformationDelta; - upsdebugx(LOG_DEBUG, "rules =[%s]", rulesString); + upsdebugx(LOG_DEBUG, "rules = [%s]", rulesString); /* state machine to process rules definition */ while((lexType=get_rule_lex(rulesString, &startPos, &endPos)) > 0 && lexStatus >= 0) { memset(lexBuff, 0, sizeof(lexBuff)); @@ -150,6 +150,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { upsfd->rules[upsfd->rulesCount-1]->stateName[endPos-startPos] = 0; } break; + case 1: if(lexType != '=') { lexStatus = -1; @@ -157,6 +158,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { lexStatus = 2; } break; + case 2: if(lexType == '^') { lexStatus = 3; @@ -168,6 +170,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { lexStatus = -1; } break; + case 3: if(lexType != '0') { lexStatus = -1; @@ -176,6 +179,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); } break; + case 4: if(lexType == '&') { lexStatus = 2; @@ -190,6 +194,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { lexStatus = -1; } break; + default: lexStatus = -1; break; @@ -199,6 +204,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { startPos = endPos; } + /* debug printout for extracted rules */ upsdebugx(LOG_DEBUG, "rules count [%d]", upsfd->rulesCount); for(i = 0; i < upsfd->rulesCount; i++) { upsdebugx( @@ -218,6 +224,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { } } + /* get gpio lines used in rules, find max line number used to check with chip lines count*/ upsfd->upsLinesCount = 0; upsfd->upsMaxLine = 0; for(i = 0; i < upsfd->rulesCount; i++) { @@ -246,6 +253,7 @@ static void get_ups_rules(struct gpioups_t *upsfd) { upsdebugx(LOG_DEBUG, "UPS line%d number %d", i, upsfd->upsLines[i]); } + /* transform lines to indexes for easier state calculation */ tranformationDelta = upsfd->upsMaxLine - RULES_CMD_LAST + 1; for(i = 0; i < upsfd->rulesCount; i++) { for(j = 0; j < upsfd->rules[i]->subCount; j++) { @@ -263,6 +271,8 @@ static void get_ups_rules(struct gpioups_t *upsfd) { } } } + + /* debug printout of transformed lines numbers */ upsdebugx(LOG_DEBUG, "rules count [%d] translated", upsfd->rulesCount); for(i = 0; i < upsfd->rulesCount; i++) { upsdebugx( @@ -422,6 +432,9 @@ void upsdrv_makevartable(void) addvar(VAR_VALUE, "rules", "Line rules to produce status strings"); addvar(VAR_SENSITIVE, "description", "Device description"); addvar(VAR_SENSITIVE, "desc", "Device description"); +#ifdef LOCALTEST + test_rules(); +#endif } void upsdrv_initups(void) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 631c168d59..6b89f82e9d 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -67,72 +67,14 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; */ -#undef LOCALTEST -#ifdef LOCALTEST -struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { - NUT_UNUSED_VARIABLE(name); - return (struct gpiod_chip *)1; -} - -unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { - NUT_UNUSED_VARIABLE(chip); - return 32; -} -int gpiod_chip_get_lines(struct gpiod_chip *chip, - unsigned int *offsets, unsigned int num_offsets, - struct gpiod_line_bulk *bulk) { - return 0; -} - -int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, - const struct gpiod_line_request_config *config, - const int *default_vals) -{ - return 0; -} - -int gStatus = 0; - -int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, - int *values) -{ - int pinPos=1; - if(gpioupsfd) - for(int i=0; iupsLinesCount; i++) { - values[i]=(gStatus&pinPos)!=0; - pinPos=pinPos<<1; - } - - gStatus++; - return 0; -} - -int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, - const struct timespec *timeout, - struct gpiod_line_bulk *event_bulk) -{ - switch(gStatus%3) { - case 0: - sleep(2); - break; - case 1: - sleep(4); - break; - case 2: - sleep(6); - break; - } - return 0; -} -#endif - /* * reserve GPIO lines as per run options and inner parameter: do reservation once * or per each status read */ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions %d, inner %d", gpioupsfd->runOptions, inner); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions 0x%x, inner %d", gpioupsfd->runOptions+1035, inner); + if(((gpioupsfd->runOptions&ROPT_REQRES) != 0) == inner) { struct gpiod_line_request_config config; int gpioRc; @@ -167,17 +109,18 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { void gpio_open(struct gpioups_t *gpioupsfd) { struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); gpioupsfd->lib_data = libgpiod_data; + libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfd->chipName); - if(!libgpiod_data->gpioChipHandle) { + if(!libgpiod_data->gpioChipHandle) fatal_with_errno( LOG_ERR, "Could not open GPIO chip [%s], check chips presence and/or access rights", gpioupsfd->chipName ); - } else { + else { int gpioRc; upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); - gpioupsfd->chipLinesCount=gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); + gpioupsfd->chipLinesCount = gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); if(gpioupsfd->chipLinesCountupsMaxLine) fatalx( @@ -229,6 +172,7 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { int i; int gpioRc; struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + reserve_lines_libgpiod(gpioupsfd, 1); if(gpioupsfd->runOptions&ROPT_EVMODE) { struct timespec timeoutLong = {1,0}; @@ -291,13 +235,16 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { &libgpiod_data->gpioLines, gpioupsfd->upsLinesStates ); + if (gpioRc < 0) fatal_with_errno(LOG_ERR, "GPIO line status read call failed"); + upsdebugx( LOG_DEBUG, "GPIO gpiod_line_get_value_bulk completed with %d return code, status values:", gpioRc ); + for(i=0; i < gpioupsfd->upsLinesCount; i++) { upsdebugx( LOG_DEBUG, @@ -306,6 +253,7 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { gpioupsfd->upsLinesStates[i] ); } + if(gpioupsfd->runOptions&ROPT_REQRES) { gpiod_line_release_bulk(&libgpiod_data->gpioLines); } From 6d8ff825898656559da0c5ba7302da5202095db3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 12:31:49 +0100 Subject: [PATCH 0518/1232] common/common.c: externalize (and rename) struct timeval upslog_start so other methods can use the same accounting --- common/common.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/common/common.c b/common/common.c index 4054cf10f5..f074fc2b3e 100644 --- a/common/common.c +++ b/common/common.c @@ -110,6 +110,8 @@ pid_t get_max_pid_t() int nut_log_level = 0; static int upslog_flags = UPSLOG_STDERR; + static struct timeval upslog_start = { 0, 0 }; + static void xbit_set(int *val, int flag) { *val |= flag; @@ -1054,21 +1056,22 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) } if (nut_debug_level > 0) { - static struct timeval start = { 0, 0 }; struct timeval now; gettimeofday(&now, NULL); - if (start.tv_sec == 0) { - start = now; + if (upslog_start.tv_sec == 0) { + upslog_start = now; } - if (start.tv_usec > now.tv_usec) { + if (upslog_start.tv_usec > now.tv_usec) { now.tv_usec += 1000000; now.tv_sec -= 1; } - fprintf(stderr, "%4.0f.%06ld\t", difftime(now.tv_sec, start.tv_sec), (long)(now.tv_usec - start.tv_usec)); + fprintf(stderr, "%4.0f.%06ld\t", + difftime(now.tv_sec, upslog_start.tv_sec), + (long)(now.tv_usec - upslog_start.tv_usec)); } if (xbit_test(upslog_flags, UPSLOG_STDERR)) From 5a75a24308c595e211ddf15fa9ed7a77cc6ebd3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 12:25:51 +0100 Subject: [PATCH 0519/1232] common/common.c: reword stderr printout as upsdebugx(1,...) pattern --- common/common.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index f074fc2b3e..5bbddac9a2 100644 --- a/common/common.c +++ b/common/common.c @@ -951,6 +951,8 @@ void nut_report_config_flags(void) * of compiled codepaths: */ const char *compiler_ver = CC_VERSION; const char *config_flags = CONFIG_FLAGS; + struct timeval now; + if (nut_debug_level < 1) return; @@ -973,8 +975,25 @@ void nut_report_config_flags(void) acinit_ver = PACKAGE_VERSION; } + /* NOTE: If changing wording here, keep in sync with configure.ac logic + * looking for CONFIG_FLAGS_DEPLOYED via "configured with flags:" string! + */ + + gettimeofday(&now, NULL); + + if (upslog_start.tv_sec == 0) { + upslog_start = now; + } + + if (upslog_start.tv_usec > now.tv_usec) { + now.tv_usec += 1000000; + now.tv_sec -= 1; + } + if (xbit_test(upslog_flags, UPSLOG_STDERR)) - fprintf(stderr, "Network UPS Tools version %s%s%s%s%s%s%s %s%s\n", + fprintf(stderr, "%4.0f.%06ld\t[D1] Network UPS Tools version %s%s%s%s%s%s%s %s%s\n", + difftime(now.tv_sec, upslog_start.tv_sec), + (long)(now.tv_usec - upslog_start.tv_usec), UPS_VERSION, (acinit_ver ? " (release/snapshot of " : ""), (acinit_ver ? acinit_ver : ""), From 6b369118a851240d54a3ecbe13f79cad076ad13d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 12:25:51 +0100 Subject: [PATCH 0520/1232] drivers/main.c: use common nut_report_config_flags() to debug-log details of the driver build --- drivers/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 1bece4f076..02ba6cdfac 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -871,9 +871,10 @@ int main(int argc, char **argv) * or issue tracker, as well as viewed locally, it can help to know the * build options involved when troubleshooting (especially when needed * to walk through building a PR branch with candidate fix for an issue). + * Reference code for such message is in common/common.c prints to log + * and/or syslog when any debug level is enabled. */ - upsdebugx(1, "Network UPS Tools version %s configured with flags: %s", - UPS_VERSION, CONFIG_FLAGS); + nut_report_config_flags(); argc -= optind; argv += optind; From 7e933d32f17ac186cece900922a4c5a5ef3e17dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:08:56 +0100 Subject: [PATCH 0521/1232] common/common.c: be sure to check for DLLs in EXE location (even if it is not "." workdir) --- common/common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/common.c b/common/common.c index 5bbddac9a2..a902a4f76e 100644 --- a/common/common.c +++ b/common/common.c @@ -1870,6 +1870,12 @@ char * get_libname(const char* base_libname) /* TODO: Need a reliable cross-platform way to get the full path * of current executable -- possibly stash it when starting NUT * programs... consider some way for `nut-scanner` too */ + if (!libname_path) { + /* First check near the EXE (if executing it from another + * working directory) */ + libname_path = get_libname_in_dir(base_libname, base_libname_length, getfullpath(NULL), counter++); + } + # ifdef PATH_LIB if (!libname_path) { libname_path = get_libname_in_dir(base_libname, base_libname_length, getfullpath(PATH_LIB), counter++); From a4d914559a79e33dc964005720b30558cf6192d4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:09:36 +0100 Subject: [PATCH 0522/1232] common/common.c: fix checking for DLLs in "../lib" relative to EXE location --- common/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index a902a4f76e..24dbc672a4 100644 --- a/common/common.c +++ b/common/common.c @@ -1884,7 +1884,7 @@ char * get_libname(const char* base_libname) if (!libname_path) { /* Resolve "lib" dir near the one with current executable ("bin" or "sbin") */ - libname_path = get_libname_in_dir(base_libname, base_libname_length, getfullpath("../lib"), counter++); + libname_path = get_libname_in_dir(base_libname, base_libname_length, getfullpath("/../lib"), counter++); } #endif /* WIN32 so far */ From feb8ce0a4b7f2c95feecfa67ceb41e70e4cfb837 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:18:03 +0100 Subject: [PATCH 0523/1232] tools/nut-scanner/nutscan-init.c: fix searching for libneon and libnetsnmp on Windows --- tools/nut-scanner/nutscan-init.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 68c2de8350..9d18d7225c 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -191,6 +191,11 @@ void nutscan_init(void) #ifdef WITH_SNMP libname = get_libname("libnetsnmp" SOEXT); + #ifdef WIN32 + if (!libname) { + libname = get_libname("libnetsnmp-40" SOEXT); + } + #endif if (libname) { nutscan_avail_snmp = nutscan_load_snmp_library(libname); free(libname); @@ -210,6 +215,14 @@ void nutscan_init(void) if (!libname) { libname = get_libname("libneon-gnutls" SOEXT); } + #ifdef WIN32 + if (!libname) { + libname = get_libname("libneon-27" SOEXT); + } + if (!libname) { + libname = get_libname("libneon-gnutls-27" SOEXT); + } + #endif if (libname) { nutscan_avail_xml_http = nutscan_load_neon_library(libname); free(libname); From 95b7939b55126b034c6daade80b3f580a281072d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:18:30 +0100 Subject: [PATCH 0524/1232] tools/nut-scanner/nutscan-init.c: first search for contemporary libupsclient DLL on Windows --- tools/nut-scanner/nutscan-init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 9d18d7225c..8d316fdd46 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -271,10 +271,10 @@ void nutscan_init(void) /* TODO: Detect DLL name at build time, or rename it at install time? */ /* e.g. see clients/Makefile.am for version-info value */ if (!libname) { - libname = get_libname("libupsclient-3" SOEXT); + libname = get_libname("libupsclient-6" SOEXT); } if (!libname) { - libname = get_libname("libupsclient-6" SOEXT); + libname = get_libname("libupsclient-3" SOEXT); } #endif if (libname) { @@ -285,10 +285,10 @@ void nutscan_init(void) nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient" SOEXT); #ifdef WIN32 if (!nutscan_avail_nut) { - nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient-3" SOEXT); + nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient-6" SOEXT); } if (!nutscan_avail_nut) { - nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient-6" SOEXT); + nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient-3" SOEXT); } #endif } From 618c58887f2d3e2f68516568a6dc3da2d010d37e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:31:02 +0100 Subject: [PATCH 0525/1232] tools/nut-scanner/nutscan-init.c: pepper with upsdebugx(1,...) to track overview progress of library loading (or not) --- tools/nut-scanner/nutscan-init.c | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 8d316fdd46..f7e0efeacc 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -169,10 +169,15 @@ void nutscan_init(void) libname = get_libname("libusb" SOEXT); } if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibUSB"); nutscan_avail_usb = nutscan_load_usb_library(libname); free(libname); } 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__, "LibUSB"); #if WITH_LIBUSB_1_0 nutscan_avail_usb = nutscan_load_usb_library("libusb-1.0" SOEXT); #else @@ -187,6 +192,11 @@ void nutscan_init(void) nutscan_avail_usb = nutscan_load_usb_library("libusb" SOEXT); } } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_usb ? "succeeded" : "failed", "LibUSB"); +#else + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibUSB"); #endif /* WITH_USB */ #ifdef WITH_SNMP @@ -197,10 +207,15 @@ void nutscan_init(void) } #endif if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibSNMP"); nutscan_avail_snmp = nutscan_load_snmp_library(libname); free(libname); } 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__, "LibSNMP"); nutscan_avail_snmp = nutscan_load_snmp_library("libnetsnmp" SOEXT); #ifdef WIN32 if (!nutscan_avail_snmp) { @@ -208,6 +223,11 @@ void nutscan_init(void) } #endif } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_snmp ? "succeeded" : "failed", "LibSNMP"); +#else + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibSNMP"); #endif /* WITH_SNMP */ #ifdef WITH_NEON @@ -224,10 +244,15 @@ void nutscan_init(void) } #endif if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibNeon"); nutscan_avail_xml_http = nutscan_load_neon_library(libname); free(libname); } 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__, "LibNeon"); nutscan_avail_xml_http = nutscan_load_neon_library("libneon" SOEXT); if (!nutscan_avail_xml_http) { nutscan_avail_xml_http = nutscan_load_neon_library("libneon-gnutls" SOEXT); @@ -241,28 +266,53 @@ void nutscan_init(void) } #endif } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_xml_http ? "succeeded" : "failed", "LibNeon"); +#else + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibNeon"); #endif /* WITH_NEON */ #ifdef WITH_AVAHI libname = get_libname("libavahi-client" SOEXT); if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibAvahi"); nutscan_avail_avahi = nutscan_load_avahi_library(libname); free(libname); } 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__, "LibAvahi"); nutscan_avail_avahi = nutscan_load_avahi_library("libavahi-client" SOEXT); } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_avahi ? "succeeded" : "failed", "LibAvahi"); +#else + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibAvahi"); #endif /* WITH_AVAHI */ #ifdef WITH_FREEIPMI libname = get_libname("libfreeipmi" SOEXT); if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibFreeIPMI"); nutscan_avail_ipmi = nutscan_load_ipmi_library(libname); free(libname); } 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__, "LibFreeIPMI"); nutscan_avail_ipmi = nutscan_load_ipmi_library("libfreeipmi" SOEXT); } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_ipmi ? "succeeded" : "failed", "LibFreeIPMI"); +#else + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibFreeIPMI"); #endif /* WITH_FREEIPMI */ /* start of libupsclient for "old NUT" (vs. Avahi) protocol - unconditional */ @@ -278,10 +328,15 @@ void nutscan_init(void) } #endif if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "NUT Client library"); nutscan_avail_nut = nutscan_load_upsclient_library(libname); free(libname); } 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__, "NUT Client library"); nutscan_avail_nut = nutscan_load_upsclient_library("libupsclient" SOEXT); #ifdef WIN32 if (!nutscan_avail_nut) { @@ -292,6 +347,8 @@ void nutscan_init(void) } #endif } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_nut ? "succeeded" : "failed", "NUT Client library"); /* end of libupsclient for "old NUT" (vs. Avahi) protocol */ } From 338d4bd9b6422f12d6dda92e4930bc28b625cfa0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 4 Mar 2023 21:33:00 +0100 Subject: [PATCH 0526/1232] common/common.c: become_user(): fix behavior with NULL arg --- common/common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 24dbc672a4..03a73e84b1 100644 --- a/common/common.c +++ b/common/common.c @@ -288,6 +288,12 @@ void become_user(struct passwd *pw) /* if we can't switch users, then don't even try */ intmax_t initial_uid = getuid(); intmax_t initial_euid = geteuid(); + + if (!pw) { + upsdebugx(1, "Can not become_user(), skipped"); + return; + } + if ((initial_euid != 0) && (initial_uid != 0)) { intmax_t initial_gid = getgid(); if (initial_euid == (intmax_t)pw->pw_uid @@ -323,7 +329,8 @@ void become_user(struct passwd *pw) #else NUT_UNUSED_VARIABLE(pw); - upsdebugx(1, "Can not become_user(%s): not implemented on this platform", pw->pw_name); + upsdebugx(1, "Can not become_user(%s): not implemented on this platform", + pw ? pw->pw_name : ""); #endif } From e451a007207cc80ccda32fcbf7929562a4354470 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 5 Mar 2023 01:37:26 +0100 Subject: [PATCH 0527/1232] ci_build.sh: try to ensure a TMPDIR --- ci_build.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index cdd0ba0c74..7c4ce2b739 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -205,6 +205,18 @@ else fi fi +if [ -z "$TMPDIR" ]; then + echo "WARNING: TMPDIR not set, trying to guess" + if [ -d /tmp -a -w /tmp ] ; then + TMPDIR=/tmp + export TMPDIR + fi +fi + +if [ -z "$TMPDIR" ]; then + echo "WARNING: TMPDIR still not set, some tools (notably clang) can fail" +fi + # For two-phase builds (quick parallel make first, sequential retry if failed) # how verbose should that first phase be? Nothing, automake list of ops, CLIs? # See build_to_only_catch_errors_target() for a consumer of this setting. From 21a2f4bb9e4c5c60173f6194b425fa78cacf894d Mon Sep 17 00:00:00 2001 From: modrisb Date: Sun, 5 Mar 2023 18:23:01 +0200 Subject: [PATCH 0528/1232] fixes after extensive rules& states calc tests --- drivers/generic_gpio_common.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index 85df2a1767..c4b24591af 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -32,7 +32,7 @@ static void generic_gpio_close(struct gpioups_t *gpioupsfd); static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString); static void add_rule_item(struct gpioups_t *upsfd, int newValue); static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); -static int calc_rule_states(int cRules[], int subCount, int sIndex); +static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex); static void update_ups_states(struct gpioups_t *gpioupsfd); /* @@ -203,6 +203,8 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); startPos = endPos; } + if(lexType == 0 && lexStatus != 0) + fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); /* debug printout for extracted rules */ upsdebugx(LOG_DEBUG, "rules count [%d]", upsfd->rulesCount); @@ -295,28 +297,30 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { /* * calculate state rule value based on GPIO line values */ -static int calc_rule_states(int cRules[], int subCount, int sIndex) { +static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex) { int ruleVal = 0; int iopStart = sIndex; int rs; - if(iopStart < subCount) { + if(iopStart < subCount) { /* calculate left side */ if(cRules[iopStart] >= 0) { - ruleVal = gpioupsfd->upsLinesStates[cRules[iopStart]]; + ruleVal = upsLinesStates[cRules[iopStart]]; } else { iopStart++; - ruleVal = !gpioupsfd->upsLinesStates[cRules[iopStart]]; + ruleVal = !upsLinesStates[cRules[iopStart]]; } iopStart++; } - if(iopStart < subCount && cRules[iopStart] == RULES_CMD_OR) { - ruleVal = ruleVal || calc_rule_states(cRules, subCount, iopStart+1); - } else { - for(; iopStart < subCount; iopStart++) { + for(; iopStart < subCount; iopStart++) { /* right side calculation */ + if(cRules[iopStart] == RULES_CMD_OR) { + ruleVal = ruleVal || calc_rule_states(upsLinesStates, cRules, subCount, iopStart+1); + break; + } else { + iopStart++; if(cRules[iopStart] == RULES_CMD_NOT) { iopStart++; - rs = !gpioupsfd->upsLinesStates[cRules[iopStart]]; + rs = !upsLinesStates[cRules[iopStart]]; } else { - rs = gpioupsfd->upsLinesStates[cRules[iopStart]]; + rs = upsLinesStates[cRules[iopStart]]; } ruleVal = ruleVal && rs; } @@ -339,6 +343,7 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { for(ruleNo = 0; ruleNo < gpioupsfd->rulesCount; ruleNo++) { gpioupsfd->rules[ruleNo]->currVal = calc_rule_states( + gpioupsfd->upsLinesStates, gpioupsfd->rules[ruleNo]->cRules, gpioupsfd->rules[ruleNo]->subCount, 0 ); @@ -432,9 +437,6 @@ void upsdrv_makevartable(void) addvar(VAR_VALUE, "rules", "Line rules to produce status strings"); addvar(VAR_SENSITIVE, "description", "Device description"); addvar(VAR_SENSITIVE, "desc", "Device description"); -#ifdef LOCALTEST - test_rules(); -#endif } void upsdrv_initups(void) From a191b043c51780780c8897703db7bb3b7a8a57b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 5 Mar 2023 19:07:30 +0100 Subject: [PATCH 0529/1232] drivers/libusb1.c: report text of libusb_error when libusb_kernel_driver_active() fails --- drivers/libusb1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 584d518527..4eddd83ebf 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -412,7 +412,8 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "successfully set kernel driver auto-detach flag"); } } else { - upsdebugx(3, "libusb_kernel_driver_active() returned %d", ret); + upsdebugx(3, "libusb_kernel_driver_active() returned %d (%s)", + ret, libusb_strerror((enum libusb_error)ret)); } #endif From b07997d0b49bfd6e717111954c4b69fc9c5635a8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 5 Mar 2023 19:23:34 +0100 Subject: [PATCH 0530/1232] common/common.c: become_user(): "pw" is not NUT_UNUSED_VARIABLE() anymore --- common/common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/common.c b/common/common.c index 03a73e84b1..5fbfed3073 100644 --- a/common/common.c +++ b/common/common.c @@ -327,8 +327,6 @@ void become_user(struct passwd *pw) upsdebugx(1, "Succeeded to become_user(%s): now UID=%jd GID=%jd", pw->pw_name, (intmax_t)getuid(), (intmax_t)getgid()); #else - NUT_UNUSED_VARIABLE(pw); - upsdebugx(1, "Can not become_user(%s): not implemented on this platform", pw ? pw->pw_name : ""); #endif From 6b152b7a789b54c5e4231d0a6c374a07eb5b9bfa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 5 Mar 2023 20:28:48 +0100 Subject: [PATCH 0531/1232] Update libusb1.c Change to conventional error-message format --- drivers/libusb1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 4eddd83ebf..b843521fdc 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -412,7 +412,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "successfully set kernel driver auto-detach flag"); } } else { - upsdebugx(3, "libusb_kernel_driver_active() returned %d (%s)", + upsdebugx(3, "libusb_kernel_driver_active() returned %d: %s", ret, libusb_strerror((enum libusb_error)ret)); } #endif From f6fefc3e32839a39189fad5aaa15cb7fe7c62b6e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 6 Mar 2023 00:08:25 +0100 Subject: [PATCH 0532/1232] nut-scanner: reformat "Cannot load ... library" reports, fix varname for libneon --- tools/nut-scanner/scan_ipmi.c | 4 +++- tools/nut-scanner/scan_snmp.c | 3 ++- tools/nut-scanner/scan_usb.c | 4 +++- tools/nut-scanner/scan_xml_http.c | 4 +++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index bb1fe4c604..d0c6d7e9f5 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -244,7 +244,9 @@ int nutscan_load_ipmi_library(const char *libname_path) return 1; err: - fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname_path, dl_error); + fprintf(stderr, + "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", + libname_path, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index b6570fd7a1..7e3568bd8c 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -437,7 +437,8 @@ int nutscan_load_snmp_library(const char *libname_path) #ifndef WITH_SNMP_STATIC err: - fprintf(stderr, "Cannot load SNMP library (%s) : %s. SNMP search disabled.\n", + fprintf(stderr, + "Cannot load SNMP library (%s) : %s. SNMP search disabled.\n", libname_path, dl_error); dl_handle = (void *)1; lt_dlexit(); diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 292c873ede..2a8c116bfe 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -205,7 +205,9 @@ int nutscan_load_usb_library(const char *libname_path) return 1; err: - fprintf(stderr, "Cannot load USB library (%s) : %s. USB search disabled.\n", libname_path, dl_error); + fprintf(stderr, + "Cannot load USB library (%s) : %s. USB search disabled.\n", + libname_path, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 74c3628d34..dcf74805e6 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -137,7 +137,9 @@ int nutscan_load_neon_library(const char *libname_path) return 1; err: - fprintf(stderr, "Cannot load XML library (%s) : %s. XML search disabled.\n", libname, dl_error); + fprintf(stderr, + "Cannot load XML library (%s) : %s. XML search disabled.\n", + libname_path, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; From eec68fc88f086225236fa382f9474221a12af20b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 6 Mar 2023 02:20:33 +0100 Subject: [PATCH 0533/1232] Update scan_xml_http.c --- tools/nut-scanner/scan_xml_http.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index dcf74805e6..80c59b5008 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -53,7 +53,6 @@ #include /* dynamic link library stuff */ -static char * libname = "libneon"; /* Note: this is for info messages, not the SONAME */ static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; From 98a065c18601c8c718674802185128add5b4ba86 Mon Sep 17 00:00:00 2001 From: modrisb Date: Mon, 6 Mar 2023 21:31:19 +0200 Subject: [PATCH 0534/1232] 2n round of refactoring after test --- drivers/generic_gpio_common.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index c4b24591af..19ebd9cb20 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -42,7 +42,13 @@ static struct gpioups_t *generic_gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ upsfdlocal->chipName=chipName; + + if(!testvar("rules")) /* rules is required configuration parameter */ + fatalx(EXIT_FAILURE, "UPS status calculation rules not specified"); + get_ups_rules(upsfdlocal, (unsigned char *)getval("rules")); + upsfdlocal->upsLinesStates = xcalloc(sizeof(int), upsfdlocal->upsLinesCount); + return upsfdlocal; } @@ -64,6 +70,7 @@ static void generic_gpio_close(struct gpioups_t *gpioupsfd) { } } free(gpioupsfd); + gpioupsfd=NULL; } } @@ -335,6 +342,7 @@ static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, in */ static void update_ups_states(struct gpioups_t *gpioupsfd) { int batLow = 0; + int bypass = 0; int chargerStatusSet = 0; int ruleNo; @@ -361,6 +369,9 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "LB")) { batLow = 1; } + if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "BYPASS")) { + bypass = 1; + } } if(gpioupsfd->aInfoAvailable && gpioupsfd->rules[ruleNo]->archVal != gpioupsfd->rules[ruleNo]->currVal) { @@ -384,6 +395,10 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { } } + if(bypass) { + dstate_delinfo("battery.charge"); + } + gpioupsfd->aInfoAvailable = 1; status_commit(); @@ -400,9 +415,6 @@ void upsdrv_initinfo(void) if(testvar("description")) { dstate_setinfo("device.description", "%s", getval("description")); } - - if(!testvar("rules")) /* rules is required configuration parameter */ - fatalx(EXIT_FAILURE, "UPS status calculation rules not specified"); } void upsdrv_updateinfo(void) From c6a47693c9de0345ec5e88c74fe082386c2d94db Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 7 Mar 2023 14:37:25 +0100 Subject: [PATCH 0535/1232] docs/developers.txt: add a chapter on IDEs --- docs/developers.txt | 36 ++++++++++++++++++++++++++++++++++++ docs/nut.dict | 8 +++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/developers.txt b/docs/developers.txt index e0f5802e48..dad434b0bd 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -430,6 +430,42 @@ Finally, note that such pre-set warnings can be mixed with options passed through `CFLAGS` or `CXXFLAGS` values to your local `configure` run, but it is up to your compiler how it interprets the resulting mix. +Integrated Development Environments (IDEs) and debugging NUT +------------------------------------------------------------ + +Much of NUT has been coded using classic editors of developers' preference, +like `vi`, `nano`, Midnight Commander `mcedit`, NotePad++ and tools like +`meld` or WinMerge for file comparison and merge. + +Modern IDEs however do offer benefits, specifically for live debugging +sessions in a more convenient fashion than with command-line `gdb` directly. +They also simplify writing AsciiDoc files with real-time rendering support. + +NOTE: Due to use of `libtool` wrappers in "autotools" driven projects, +it may be tricky to attach the debugger (mixing the correct `LD_LIBRARY_PATH` +or equivalent with a binary under a `.libs` subdirectory). + +IDEs that were tested to work with NUT development and real-time debugger +tracing include: + +* Sun NetBeans 8.2 on Solaris, Linux (including local and remote build + and debug ability); +* Apache NetBeans 17 on Windows with MSYS2 support (as MinGW toolkit); +* Visual Studio Code (VSCode) on Windows with MSYS2 support. + +//////// +TODO: Expand on adding include and library paths to NetBeans on Windows. +Plugins: unpack200 from JDK11 or older to install NB8.2 repo C/C++ plugins. + +TODO: Expand on tools.json and launcher.json in VSCode on Windows + +TODO: Expand on envvars settings for MSYS to be callable on Windows +(e.g. avoid NetBeans claims of missing shell). + +Make note of settings (and Run as Administrator) to use symlinks in MinGW x64. +Check if required for sane (iterative re-)builds? ;) +//////// + Coding style ------------ diff --git a/docs/nut.dict b/docs/nut.dict index 46268676ec..3a464ea49a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3096 utf-8 +personal_ws-1.1 en 3102 utf-8 AAS ABI ACFAIL @@ -761,6 +761,7 @@ Nash NaturalDocs Necedah NetBSD +NetBeans NetPro NetServer NetUps @@ -775,6 +776,7 @@ Nom NomDCV NomVIn NomVOut +NotePad Novell NrLoBatt NutException @@ -1321,6 +1323,7 @@ VMM VMware VNC VPATH +VSCode VSN VTIME VV @@ -1918,6 +1921,7 @@ gcc gcpp gd gd's +gdb gdlib ge genericsups @@ -2240,6 +2244,7 @@ maxvalue maxvi maxvo mc +mcedit md mdadm mecer @@ -2320,6 +2325,7 @@ nLogic nabcd nameserver namespace +nano nanosleep nashkaminski natively From 3efe9544e68ce33dec06827443b7cefdeb5a1b7b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 7 Mar 2023 16:56:28 +0100 Subject: [PATCH 0536/1232] ci_build.sh: add rudimentary support for "./ci_build.sh spellcheck-interactive" --- ci_build.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 7c4ce2b739..6fe34cb7df 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -161,7 +161,7 @@ case "${CI_BUILDDIR-}" in ;; esac -[ -n "$MAKE" ] || [ "$1" = spellcheck ] || MAKE=make +[ -n "$MAKE" ] || [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] || MAKE=make [ -n "$GGREP" ] || GGREP=grep [ -n "$MAKE_FLAGS_QUIET" ] || MAKE_FLAGS_QUIET="VERBOSE=0 V=0 -s" @@ -720,7 +720,7 @@ if [ "$1" = inplace ] && [ -z "$BUILD_TYPE" ] ; then BUILD_TYPE="inplace" fi -if [ "$1" = spellcheck ] && [ -z "$BUILD_TYPE" ] ; then +if [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] && [ -z "$BUILD_TYPE" ] ; then # Note: this is a little hack to reduce typing # and scrolling in (docs) developer iterations. if [ -z "${MAKE-}" ] ; then @@ -754,8 +754,12 @@ if [ "$1" = spellcheck ] && [ -z "$BUILD_TYPE" ] ; then esac >&2 if [ -s Makefile ] && [ -s docs/Makefile ]; then echo "Processing quick and quiet spellcheck with already existing recipe files, will only report errors if any ..." - build_to_only_catch_errors_target spellcheck ; exit + build_to_only_catch_errors_target $1 ; exit else + # TODO: Actually do it (default-spellcheck-interactive)? + if [ "$1" = spellcheck-interactive ] ; then + echo "Only CI-building 'spellcheck', please do the interactive part manually if needed" >&2 + fi BUILD_TYPE="default-spellcheck" shift fi From 8861a9969a72b75578ca6af674bd0f4f63fdac33 Mon Sep 17 00:00:00 2001 From: modrisb Date: Tue, 7 Mar 2023 21:04:31 +0200 Subject: [PATCH 0537/1232] adding 2 missed commits --- drivers/generic_gpio_libgpiod.c | 5 +++-- m4/nut_check_libgpiod.m4 | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 6b89f82e9d..95dedf5c98 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -122,14 +122,15 @@ void gpio_open(struct gpioups_t *gpioupsfd) { upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); gpioupsfd->chipLinesCount = gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); - if(gpioupsfd->chipLinesCountupsMaxLine) + if(gpioupsfd->chipLinesCountupsMaxLine) { + gpiod_chip_close(libgpiod_data->gpioChipHandle); fatalx( LOG_ERR, "GPIO chip lines count %d smaller than UPS line number used (%d)", gpioupsfd->chipLinesCount, gpioupsfd->upsMaxLine ); - gpioupsfd->upsLinesStates = xcalloc(sizeof(int), gpioupsfd->upsLinesCount); + } gpiod_line_bulk_init(&libgpiod_data->gpioLines); gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); gpioRc = gpiod_chip_get_lines( diff --git a/m4/nut_check_libgpiod.m4 b/m4/nut_check_libgpiod.m4 index 319e1c308c..45e3ae61f2 100644 --- a/m4/nut_check_libgpiod.m4 +++ b/m4/nut_check_libgpiod.m4 @@ -17,8 +17,8 @@ if test -z "${nut_have_gpio_seen}"; then [dnl See which version of the gpiod library (if any) is installed dnl FIXME : Support detection of cflags/ldflags below by legacy dnl discovery if pkgconfig is not there - AC_MSG_CHECKING(for libgpiod-dev version via pkg-config (1.0.0 minimum required)) - GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion libgpiod-dev 2>/dev/null`" + AC_MSG_CHECKING(for libgpiod version via pkg-config (1.0.0 minimum required)) + GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion libgpiod 2>/dev/null`" if test "$?" != "0" -o -z "${GPIO_VERSION}"; then GPIO_VERSION="none" fi @@ -43,7 +43,7 @@ if test -z "${nut_have_gpio_seen}"; then esac ], [ AS_IF([test x"$have_PKG_CONFIG" = xyes], - [CFLAGS="`$PKG_CONFIG --silence-errors --cflags libgpiod-dev 2>/dev/null`" || CFLAGS="-I/usr/include -I/usr/local/include"], + [CFLAGS="`$PKG_CONFIG --silence-errors --cflags libgpiod 2>/dev/null`" || CFLAGS="-I/usr/include -I/usr/local/include"], [CFLAGS="-I/usr/include -I/usr/local/include"] )] ) @@ -63,7 +63,7 @@ if test -z "${nut_have_gpio_seen}"; then esac ], [ AS_IF([test x"$have_PKG_CONFIG" = xyes], - [LIBS="`$PKG_CONFIG --silence-errors --libs libgpiod-dev 2>/dev/null`" || LIBS="-lgpiod"], + [LIBS="`$PKG_CONFIG --silence-errors --libs libgpiod 2>/dev/null`" || LIBS="-lgpiod"], [LIBS="-lgpiod"] )] ) @@ -71,7 +71,7 @@ if test -z "${nut_have_gpio_seen}"; then dnl check if gpiod is usable AC_CHECK_HEADERS(gpiod.h, [nut_have_gpio=yes], [nut_have_gpio=no], [AC_INCLUDES_DEFAULT]) - AC_CHECK_FUNCS(gpiod_chip_open_by_name gpiod_line_get_value_bulk gpiod_chip_close, [], [nut_have_gpio=no]) + AC_CHECK_FUNCS(gpiod_chip_open_by_name gpiod_chip_close, [], [nut_have_gpio=no]) if test "${nut_have_gpio}" = "yes"; then LIBGPIO_CFLAGS="${CFLAGS}" From 6870d8bc4ac904728a6ec7366aa6fffe13dd8758 Mon Sep 17 00:00:00 2001 From: modrisb Date: Tue, 7 Mar 2023 21:30:59 +0200 Subject: [PATCH 0538/1232] libgpiod formatting --- drivers/generic_gpio_libgpiod.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 95dedf5c98..00674b99f2 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -46,7 +46,6 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); Open when battery is missing 3 LOW BATTERY Low when battery is near full charge capacity Open when operating from a battery with < 20% capacity - NUT supported states OL On line (mains is present) OB On battery (mains is not present) @@ -62,7 +61,6 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); TRIM UPS is trimming incoming voltage (called "buck" in some hardware) BOOST UPS is boosting incoming voltage FSD Forced Shutdown (restricted use, see the note below) - CyberPower rules setting OL=^0;OB=0;LB=3;HB=^3;RB=1;DISCHRG=0&^3;BYPASS=6; */ From e35ddbceb770b6fb6c8570f6290f244b1b6f3535 Mon Sep 17 00:00:00 2001 From: modrisb Date: Tue, 7 Mar 2023 22:24:46 +0200 Subject: [PATCH 0539/1232] added tests for gpio --- tests/Makefile.am | 7 + tests/generic_gpio_liblocal.c | 133 ++++++++++++++ tests/generic_gpio_test.txt | 134 +++++++++++++++ tests/generic_gpio_utest.c | 315 ++++++++++++++++++++++++++++++++++ 4 files changed, 589 insertions(+) create mode 100644 tests/generic_gpio_liblocal.c create mode 100644 tests/generic_gpio_test.txt create mode 100644 tests/generic_gpio_utest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 7cd1d984fb..9cb85e5044 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -58,6 +58,13 @@ getvaluetest_CFLAGS = $(AM_CFLAGS) $(LIBUSB_CFLAGS) getvaluetest_LDADD = $(top_builddir)/common/libcommon.la endif +if WITH_GPIO +TESTS += gpiotest + +gpiotest_SOURCES = generic_gpio_utest.c +gpiotest_LDADD = $(top_builddir)/common/libcommon.la +endif + # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/common/libcommon.la: dummy @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c new file mode 100644 index 0000000000..ad9e5cbf74 --- /dev/null +++ b/tests/generic_gpio_liblocal.c @@ -0,0 +1,133 @@ +/* generic_gpio_libglocal.c - gpio device emulation library for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * + * 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 "common.h" +#include +#include +#include "generic_gpio_common.h" +#include "generic_gpio_libgpiod.h" + +static char chipName[16]; +static unsigned int num_lines=0; + +struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { + strcpy(chipName, name); + if(strcmp(name, "gpiochip1")) + return (struct gpiod_chip *)1; + else { + errno = EACCES; + return NULL; + } +} + +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) { + NUT_UNUSED_VARIABLE(chip); + NUT_UNUSED_VARIABLE(offsets); + NUT_UNUSED_VARIABLE(bulk); + num_lines=num_offsets; + return 0; +} + +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); + NUT_UNUSED_VARIABLE(default_vals); + return 0; +} + +static int gStatus = 0; +static int errReqFor_line_get_value_bulk=0; + +void setNextLinesReadToFail() { + errReqFor_line_get_value_bulk=1; +} + +int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, + int *values) +{ + NUT_UNUSED_VARIABLE(bulk); + if(errReqFor_line_get_value_bulk) { + errReqFor_line_get_value_bulk=0; + errno = EPERM; + return -1; + } + int pinPos=1; + for(unsigned int i=0; i + * + * 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 "config.h" +#include "main.h" +#include "attribute.h" +#include "generic_gpio_common.c" +#include + +#include "generic_gpio_liblocal.c" +#include "generic_gpio_libgpiod.c" + +#include +#include + +#define main ignore +#include "main.c" +#undef main +#include "dstate.c" + +extern struct gpioups_t *gpioupsfd; + +static int done=0; +static int test_with_exit; +static jmp_buf env_buffer; +static FILE * testData; +static int fEof; +static int cases_passed; +static int cases_failed; + +static char * pass_fail[2] = {"pass", "fail"}; + +void getWithoutUnderscores(char *var) { + fEof=fscanf(testData, "%s", var); + for(int i=0; var[i]; i++) { + if(var[i]=='_') var[i]=' '; + } +} + +#define MFR "CyberPower" +#define MODEL "CyberShield CSN27U12V" +#define DESCRIPTION "modem and DNS server UPS" + +int get_test_status(struct gpioups_t *result, int on_fail_path) { + int expecting_failure; + int upsLinesCount; /* no of lines used in rules */ + int upsMaxLine; /* maximum line number referenced in rules */ + int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ + char stateName[12]; /* NUT state name for rules in cRules */ + int subCount; /* element count in translated rules subitem */ + int ruleInt; + + fEof=fscanf(testData, "%d", &expecting_failure); + if(on_fail_path) { + if(expecting_failure) cases_failed++; else cases_passed++; + return expecting_failure; + } + + if(!expecting_failure) { + cases_failed++; + printf("expecting case to fail\n"); + return 1; + } + + fEof=fscanf(testData, "%d", &upsLinesCount); + if(result->upsLinesCount!=upsLinesCount) { + cases_failed++; + printf("expecting upsLinesCount %d, got %d\n", upsLinesCount, result->upsLinesCount); + return 1; + } + + fEof=fscanf(testData, "%d", &upsMaxLine); + if(result->upsMaxLine!=upsMaxLine) { + cases_failed++; + printf("expecting rulesCount %d, got %d\n", upsMaxLine, result->upsMaxLine); + return 1; + } + + fEof=fscanf(testData, "%d", &rulesCount); + if(result->rulesCount!=rulesCount) { + cases_failed++; + printf("expecting rulesCount %d, got %d\n", rulesCount, result->rulesCount); + return 1; + } + + for(int i=0; irulesCount; i++) { + fEof=fscanf(testData, "%s", stateName); + if(!strcmp(result->rules[i]->stateName,stateName)) { + cases_failed++; + printf("expecting stateName %s, got %s for rule %d\n", stateName, result->rules[i]->stateName, i); + return 1; + } + fEof=fscanf(testData, "%d", &subCount); + if(result->rules[i]->subCount!=subCount) { + cases_failed++; + printf("expecting subCount %d, got %d for rule %d\n", result->rules[i]->subCount, subCount, i); + return 1; + } + for(int j=0; jrules[i]->cRules[j]!=ruleInt) { + cases_failed++; + printf("expecting cRule %d, got %d for rule %d subRule %d\n", ruleInt, result->rules[i]->cRules[j], i, j); + return 1; + } + } + } + + cases_passed++; + return 0; +} + +void exit(int code) +{ + if (!done) { + longjmp(env_buffer, 1); + } + else { + _exit(code); + } +} + +int main(int argc, char **argv) { + test_with_exit=0; + int jmp_result; + char rules[128]; + char testType[128]; + char *testDescFileName="./generic_gpio_test.txt"; + if(argc==2) { + testDescFileName=argv[1]; + } + testData = fopen (testDescFileName, "r"); + if(!testData) { + done = 1; + printf("failed to open test description file %s\n", testDescFileName); + exit(EXIT_FAILURE); + } + + cases_passed=0; + cases_failed=0; + fEof = 1; + for(unsigned int i=0; fEof!=EOF; i++) { + do { + fEof=fscanf(testData, "%s", rules); + } while(strcmp("*", rules)); + fEof=fscanf(testData, "%s", testType); + fEof=fscanf(testData, "%s", rules); + if(fEof!=EOF) { + if(!strcmp(testType, "rules")) { + jmp_result = setjmp(env_buffer); + struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + if(jmp_result) { /* test case exiting */ + generic_gpio_close(upsfdtest); + printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 1)], testType, i, rules); + } else { /* run test case */ + get_ups_rules(upsfdtest, (unsigned char *)rules); + generic_gpio_close(upsfdtest); + printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 0)], testType, i, rules); + } + } + if(!strcmp(testType, "states")) { + int expectedStateValue; + int calculatedStateValue; + struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + get_ups_rules(upsfdtest, (unsigned char *)rules); + upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); + for(int j=0; jupsLinesCount; j++) { + fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); + } + for(int j=0; jrulesCount; j++) { + fEof=fscanf(testData, "%d", &expectedStateValue); + calculatedStateValue=calc_rule_states(upsfdtest->upsLinesStates, upsfdtest->rules[j]->cRules, upsfdtest->rules[j]->subCount, 0); + if(expectedStateValue==calculatedStateValue) { + printf("%s %s test rule %d [%s]\n", pass_fail[0], testType, i, rules); + cases_passed++; + } else { + printf("%s %s test rule %d [%s] %s", pass_fail[1], testType, i, rules, upsfdtest->rules[j]->stateName); + for(int k=0; kupsLinesCount; k++) { + printf(" %d", upsfdtest->upsLinesStates[k]); + } + printf("\n"); + cases_failed++; + } + } + generic_gpio_close(upsfdtest); + } + if(!strcmp(testType, "update")) { + char upsStatus[256]; + char chargeStatus[256]; + char chargeLow[256]; + char charge[256]; + struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + get_ups_rules(upsfdtest, (unsigned char *)rules); + upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); + for(int j=0; jupsLinesCount; j++) { + fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); + } + getWithoutUnderscores(upsStatus); + getWithoutUnderscores(chargeStatus); + getWithoutUnderscores(chargeLow); + getWithoutUnderscores(charge); + if(strcmp(chargeLow, ".")) + dstate_setinfo("battery.charge.low", "%s", chargeLow); + jmp_result = setjmp(env_buffer); + int failed=0; + const char *currUpsStatus=NULL; + const char *currChargerStatus=NULL; + const char *currCharge=NULL; + if(jmp_result) { + failed=1; + generic_gpio_close(upsfdtest); + } else { + update_ups_states(upsfdtest); + currUpsStatus=dstate_getinfo("ups.status"); + currChargerStatus=dstate_getinfo("battery.charger.status"); + currCharge=dstate_getinfo("battery.charge"); + if(strcmp(currUpsStatus, upsStatus)) failed=1; + if( strcmp(chargeStatus,".") && (!currChargerStatus || strcmp(currChargerStatus, chargeStatus))) failed=1; + if(!strcmp(chargeStatus,".") && currChargerStatus!=NULL) failed=1; + if( strcmp(chargeLow,".") && strcmp(charge,".") && (!currCharge || strcmp(currCharge, charge))) failed=1; + if(!strcmp(chargeLow,".") && !strcmp(charge,".") && currCharge!=NULL) failed=1; + generic_gpio_close(upsfdtest); + } + printf("%s %s test rule %d [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", + pass_fail[failed], testType, i, rules, + upsStatus, chargeStatus, charge, chargeLow, + currUpsStatus, currChargerStatus, currCharge); + if(!failed) { + cases_passed++; + } else { + cases_failed++; + } + vartab_free(); vartab_h = NULL; + } + if(!strcmp(testType, "library")) { + char chipName[32]; + int expecting_failure; + char subType[16]; + fEof=fscanf(testData, "%d", &expecting_failure); + fEof=fscanf(testData, "%s", chipName); + fEof=fscanf(testData, "%s", subType); + jmp_result = setjmp(env_buffer); + int failed=expecting_failure; + if(jmp_result) { /* test case exiting */ + if(expecting_failure) failed=0; + upsdrv_cleanup(); + } else { + if(expecting_failure) failed=1; + device_path = chipName; + if(strcmp(subType, "initinfo") || !expecting_failure) { + addvar(VAR_VALUE, "rules", ""); + storeval("rules", rules); + } + addvar(VAR_SENSITIVE, "mfr", MFR); + storeval("mfr", MFR); + addvar(VAR_SENSITIVE, "model", MODEL); + storeval("model", MODEL); + addvar(VAR_SENSITIVE, "description", DESCRIPTION); + storeval("description", DESCRIPTION); + upsdrv_initups(); + if(!strcmp(subType, "initinfo")) { + upsdrv_makevartable(); + if(expecting_failure) setNextLinesReadToFail(); + upsdrv_initinfo(); + if(!dstate_getinfo("device.mfr") || strcmp(dstate_getinfo("device.mfr"), MFR) || + !dstate_getinfo("device.model") || strcmp(dstate_getinfo("device.model"), MODEL) || + !dstate_getinfo("device.description") || strcmp(dstate_getinfo("device.description"), DESCRIPTION)) failed=1; + } + if(!strcmp(subType, "updateinfo")) { + for(int k=0; kupsLinesCount; k++) { + gpioupsfd->upsLinesStates[k]=-1; + } + if(expecting_failure) setNextLinesReadToFail(); + upsdrv_updateinfo(); + for(int k=0; kupsLinesCount && failed!=1; k++) { + if(gpioupsfd->upsLinesStates[k]<0) failed=1; + } + } + upsdrv_cleanup(); + } + printf("%s %s %s test rule %d [%s] %s %d\n", + pass_fail[failed], testType, subType, i, rules, chipName, expecting_failure); + if(!failed) { + cases_passed++; + } else { + cases_failed++; + } + vartab_free(); vartab_h = NULL; + } + } + } + + printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); + fclose(testData); + done = 1; +} From 7d7d70a9bb6a690ac760c8641f7ef7cdf76dd903 Mon Sep 17 00:00:00 2001 From: modrisb Date: Tue, 7 Mar 2023 22:41:52 +0200 Subject: [PATCH 0540/1232] fixed debug print in common --- drivers/generic_gpio_libgpiod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 00674b99f2..8927d636a8 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -71,7 +71,7 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); */ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions 0x%x, inner %d", gpioupsfd->runOptions+1035, inner); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions 0x%x, inner %d", gpioupsfd->runOptions, inner); if(((gpioupsfd->runOptions&ROPT_REQRES) != 0) == inner) { struct gpiod_line_request_config config; From 4a900c7e4c380903ea8a3f6361a45d387598d9d9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 13:23:56 +0100 Subject: [PATCH 0541/1232] configure.ac: currently --with-gpio defaults are platform-dependent --- configure.ac | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 628cbf924f..5cbbc510ae 100644 --- a/configure.ac +++ b/configure.ac @@ -1170,9 +1170,16 @@ 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_gpio}"; then with_gpio="yes"; fi dnl Platform-dependent snowflakes that are required or auto: + if test -z "${with_gpio}"; then + dnl NOTE: Currently we only support a Linux libgpiod + dnl backend for GPIO; eventually there could be more. + case ${target_os} in + linux*) with_gpio="yes";; + *) with_gpio="auto";; + esac + fi if test -z "${with_linux_i2c}"; then case ${target_os} in linux*) with_linux_i2c="yes";; @@ -1378,9 +1385,17 @@ 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_gpio}"; then with_gpio="${withval}"; fi dnl Platform-dependent snowflakes that are required or auto: + if test -z "${with_gpio}"; then + dnl NOTE: Currently we only support a Linux libgpiod + dnl backend for GPIO; eventually there could be more. + with_gpio="${withval}" + case ${target_os} in + linux*) ;; + *) test x"${withval}" = xno || with_gpio="auto" ;; + esac + fi if test -z "${with_linux_i2c}"; then with_linux_i2c="${withval}" case ${target_os} in From 15b1788be6b1228369dee097aa8edffd927013f3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 13:40:47 +0100 Subject: [PATCH 0542/1232] NEWS, UPGRADING, docs/configure.txt, docs/packager-guide.txt: mention new category of GPIO drivers --- NEWS | 7 +++++++ UPGRADING | 4 ++++ docs/configure.txt | 10 ++++++++++ docs/packager-guide.txt | 9 +++++++++ 4 files changed, 30 insertions(+) diff --git a/NEWS b/NEWS index f5b85d8bbd..d9a5f8031d 100644 --- a/NEWS +++ b/NEWS @@ -139,6 +139,13 @@ https://github.com/networkupstools/nut/milestone/8 - The `bestfortress` driver shutdown handling was fixed to use a non-trivial default timeout [#1820] + - GPIO drivers [#1855]: + * Added a new category of drivers, using GPIO interface to locally connected + devices (currently limited to Linux libgpiod, but its architecture was + designed to later support more OSes with their equivalents - PRs welcome) + * `generic_gpio_libgpiod` driver using `libgpiod` backend was added + (defaults to be required on Linux, optional on other platforms) + - Added support for `make install` of PyNUT module and NUT-Monitor desktop application [#1462, #1504] diff --git a/UPGRADING b/UPGRADING index 47bc73c3a1..7c9cf4ddce 100644 --- a/UPGRADING +++ b/UPGRADING @@ -69,6 +69,10 @@ Changes from 2.8.0 to 2.8.1 serial drivers in respective Makefile and configure script options - this may impact packaging decisions on some distributions going forward [#1446] +- GPIO category of drivers was added (`--with-gpio` configure script option) - + this may impact packaging decisions on some (currently Linux) distributions + going forward [#1855] + - An explicit `configure --with-nut-scanner` toggle was added, specifically so that build environments requesting `--with-all` but lacking `libltdl` would abort and require the packager either to install the dependency diff --git a/docs/configure.txt b/docs/configure.txt index e5a93ea505..8f3d78d609 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -169,6 +169,16 @@ Build and install i2c drivers (default: auto-detect) Note that you need to install libi2c development package or files. +GPIO bus drivers +~~~~~~~~~~~~~~~~ + + --with-gpio + +Build and install GPIO drivers (default: auto-detect) + +Note that on Linux you need to install libgpiod development package or files. +Other platforms are not currently supported, but may be in the future. + Modbus drivers ~~~~~~~~~~~~~~ diff --git a/docs/packager-guide.txt b/docs/packager-guide.txt index 60ccb0f24d..123ab417d0 100644 --- a/docs/packager-guide.txt +++ b/docs/packager-guide.txt @@ -178,6 +178,7 @@ FIXME: make a dependency graph - <> - <> +- <> (currently platform-dependent) - <> (platform-dependent) - <> (platform-dependent) @@ -296,6 +297,14 @@ nut-modbus - Size: - Deps: +[[pkg-nut-gpio]] +nut-gpio +^^^^^^^^ +- Desc: (currently platform-dependent) +- Files: +- Size: +- Deps: + [[pkg-nut-linux-i2c]] nut-linux-i2c ^^^^^^^^^^^^^ From 9835ed61451c307a1f4f78f8708a2bef6871bf2f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 01:16:40 +0100 Subject: [PATCH 0543/1232] drivers/libusb{0,1}.c: suggest Zadig tool to handle UPS with WinUSB (for WIN32 builds) --- drivers/libusb0.c | 14 ++++++++++++++ drivers/libusb1.c | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 4fd12c7bd6..ef94d6ca33 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -566,9 +566,23 @@ static int libusb_open(usb_dev_handle **udevp, if (res < rdlen) { +#ifndef WIN32 upsdebugx(2, "Warning: report descriptor too short " "(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE ", got %d)", rdlen, res); +#else + /* https://github.com/networkupstools/nut/issues/1690#issuecomment-1455206002 */ + upsdebugx(0, "Warning: report descriptor too short " + "(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE + ", got %d)", rdlen, res); + upsdebugx(0, "Please check your Windows Device Manager: " + "perhaps the UPS was recognized by default OS\n" + "driver such as HID UPS Battery (hidbatt.sys, " + "hidusb.sys or similar). It could have been\n" + "\"restored\" by Windows Update. You can try " + "https://zadig.akeo.ie/ to handle it with\n" + "either WinUSB, libusb0.sys or libusbK.sys."); +#endif /* WIN32 */ rdlen = res; /* correct rdlen if necessary */ } diff --git a/drivers/libusb1.c b/drivers/libusb1.c index b843521fdc..530633bf6a 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -625,8 +625,21 @@ static int nut_libusb_open(libusb_device_handle **udevp, if (res < rdlen) { +#ifndef WIN32 upsdebugx(2, "Warning: report descriptor too short " "(expected %d, got %d)", rdlen, res); +#else + /* https://github.com/networkupstools/nut/issues/1690#issuecomment-1455206002 */ + upsdebugx(0, "Warning: report descriptor too short " + "(expected %d, got %d)", rdlen, res); + upsdebugx(0, "Please check your Windows Device Manager: " + "perhaps the UPS was recognized by default OS\n" + "driver such as HID UPS Battery (hidbatt.sys, " + "hidusb.sys or similar). It could have been\n" + "\"restored\" by Windows Update. You can try " + "https://zadig.akeo.ie/ to handle it with\n" + "either WinUSB, libusb0.sys or libusbK.sys."); +#endif /* WIN32 */ rdlen = res; /* correct rdlen if necessary */ } From 091941028ee113ee2531e7bed1bcfc6ec8438d29 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 13:48:53 +0100 Subject: [PATCH 0544/1232] configure.ac: relocate all "NUT_ARG_WITH(build and install ... driver)" together, so they are nearby in configure --help --- configure.ac | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 7548fc0831..049da66ef4 100644 --- a/configure.ac +++ b/configure.ac @@ -1481,6 +1481,16 @@ NUT_CHECK_LIBMODBUS NUT_ARG_WITH([avahi], [build and install Avahi support], [auto]) NUT_CHECK_LIBAVAHI +NUT_ARG_WITH([ipmi], [build and install IPMI PSU driver], [auto]) +NUT_ARG_WITH([freeipmi], [enable IPMI support using FreeIPMI], [auto]) +dnl NUT_ARG_WITH([openipmi], [enable IPMI support using OpenIPMI], [auto]) + +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]) + dnl A Python GUI client application for the sysadmin desktop dnl (not necessarily on the NUT server itself): NUT_ARG_WITH([nut_monitor], [install the NUT-Monitor GUI files], [auto]) @@ -1659,10 +1669,6 @@ dnl if both are available (since it is the only one supported ATM!!) nut_ipmi_lib="" -NUT_ARG_WITH([ipmi], [build and install IPMI PSU driver], [auto]) -NUT_ARG_WITH([freeipmi], [enable IPMI support using FreeIPMI], [auto]) -dnl NUT_ARG_WITH([openipmi], [enable IPMI support using OpenIPMI], [auto]) - dnl ${nut_with_ipmi}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_ipmi}" != "no"; then dnl check if FreeIPMI (and maybe later OpenIPMI) was explicitly requested @@ -1726,7 +1732,6 @@ dnl the internal USB UPS driver. dnl dnl FIXME: be slightly more clever here: -NUT_ARG_WITH([macosx_ups], [build and install Mac OS X Power Sources meta-driver], [auto]) if test "${nut_with_macosx_ups}" != no; then if test -d /System/Library/Frameworks/IOKit.framework/ ; then nut_with_macosx_ups="yes" @@ -1745,7 +1750,6 @@ NUT_REPORT_FEATURE([build Mac OS X meta-driver], dnl ---------------------------------------------------------------------- dnl checks related to --with_linux_i2c dnl Check for i2c header on Linux, used for ASEM UPS driver -NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) LIBI2C_LIBS="" if test "${nut_with_linux_i2c}" != no; then case ${target_os} in From ea05968d21192c2d2c17a566ac49844eb10679d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 13:54:39 +0100 Subject: [PATCH 0545/1232] m4/nut_check_pkgconfig.m4: fix AS_HELP_STRING (program name; not optional) --- m4/nut_check_pkgconfig.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nut_check_pkgconfig.m4 b/m4/nut_check_pkgconfig.m4 index 263be4bed5..fd9a2449ef 100644 --- a/m4/nut_check_pkgconfig.m4 +++ b/m4/nut_check_pkgconfig.m4 @@ -27,7 +27,7 @@ AS_IF([test -z "${nut_have_pkg_config_seen}"], [ AC_PATH_PROG(dummy_PKG_CONFIG, pkg-config) AC_ARG_WITH(pkg-config, - AS_HELP_STRING([@<:@--with-pkg-config=/path/to/gdlib-config@:>@], + AS_HELP_STRING([--with-pkg-config=/path/to/pkg-config], [path to program that reports development package configuration]), [ case "${withval}" in From aed2518237486155170452ac82375a5169ff92f1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 13:50:40 +0100 Subject: [PATCH 0546/1232] configure.ac: relocate all "NUT_ARG_WITH(build and install GPIO driver)" to other drivers, so they are nearby in configure --help --- configure.ac | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 5cbbc510ae..c37e50d89a 100644 --- a/configure.ac +++ b/configure.ac @@ -1501,6 +1501,10 @@ NUT_CHECK_LIBPOWERMAN NUT_ARG_WITH([modbus], [build and install modbus drivers], [auto]) NUT_CHECK_LIBMODBUS +NUT_ARG_WITH([gpio], [build and install GPIO driver], [auto]) +nut_gpio_lib="" +NUT_CHECK_LIBGPIO + NUT_ARG_WITH([avahi], [build and install Avahi support], [auto]) NUT_CHECK_LIBAVAHI @@ -1745,11 +1749,6 @@ dnl AM_CONDITIONAL(WITH_OPENIPMI, test "${nut_with_openipmi}" = "yes") dnl ---------------------------------------------------------------------- dnl Check for with-gpio -nut_gpio_lib="" - -NUT_ARG_WITH([gpio], [build and install GPIO driver], [auto]) - -NUT_CHECK_LIBGPIO dnl ${nut_with_gpio}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_gpio}" != "yes"; then From 8f2beb863e44186ba28bfc34619fdb4e88e684e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 14:02:51 +0100 Subject: [PATCH 0547/1232] drivers/Makefile.am: add generic_gpio*.h to dist_noinst_HEADERS --- drivers/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 855926ea0c..ec16ee8aa6 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -339,6 +339,7 @@ nutdrv_qx_SOURCES += $(NUTDRV_QX_SUBDRIVERS) dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mib.h bcmxcp.h bcmxcp_ser.h \ bcmxcp_io.h belkin.h belkin-hid.h bestpower-mib.h blazer.h cps-hid.h dstate.h \ dummy-ups.h explore-hid.h gamatronic.h genericups.h \ + generic_gpio_common.h generic_gpio_libgpiod.h \ hidparser.h hidtypes.h ietf-mib.h libhid.h libshut.h nut_libusb.h liebert-hid.h \ main.h mge-hid.h mge-mib.h mge-utalk.h \ mge-xml.h microdowell.h microsol-apc.h microsol-common.h netvision-mib.h netxml-ups.h nut-ipmi.h oneac.h \ From 5f011cd692522086d702fee7972ea6b3428ed231 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 14:19:16 +0100 Subject: [PATCH 0548/1232] configure.ac, m4/nut_check_libgpiod.m4: fix actual --with-gpio handling --- configure.ac | 8 +++++--- m4/nut_check_libgpiod.m4 | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c37e50d89a..11bc7e8ad7 100644 --- a/configure.ac +++ b/configure.ac @@ -1502,7 +1502,6 @@ NUT_ARG_WITH([modbus], [build and install modbus drivers], [auto]) NUT_CHECK_LIBMODBUS NUT_ARG_WITH([gpio], [build and install GPIO driver], [auto]) -nut_gpio_lib="" NUT_CHECK_LIBGPIO NUT_ARG_WITH([avahi], [build and install Avahi support], [auto]) @@ -1749,10 +1748,13 @@ dnl AM_CONDITIONAL(WITH_OPENIPMI, test "${nut_with_openipmi}" = "yes") dnl ---------------------------------------------------------------------- dnl Check for with-gpio +if test "${nut_with_gpio}" = "yes" -a "${nut_have_gpio}" != "yes"; then + AC_MSG_ERROR([No supported GPIO library was found, required for GPIO driver]) +fi dnl ${nut_with_gpio}: any value except "yes" or "no" is treated as "auto". -if test "${nut_with_gpio}" != "yes"; then - nut_with_gpio="no" +if test "${nut_with_gpio}" != "no"; then + nut_with_gpio="${nut_have_gpio}" fi NUT_REPORT_FEATURE([build GPIO driver], [${nut_with_gpio}], [${nut_gpio_lib}], diff --git a/m4/nut_check_libgpiod.m4 b/m4/nut_check_libgpiod.m4 index 45e3ae61f2..b946b63dbc 100644 --- a/m4/nut_check_libgpiod.m4 +++ b/m4/nut_check_libgpiod.m4 @@ -12,6 +12,7 @@ if test -z "${nut_have_gpio_seen}"; then dnl save CFLAGS and LIBS CFLAGS_ORIG="${CFLAGS}" LIBS_ORIG="${LIBS}" + nut_gpio_lib="" AS_IF([test x"$have_PKG_CONFIG" = xyes], [dnl See which version of the gpiod library (if any) is installed @@ -21,6 +22,8 @@ if test -z "${nut_have_gpio_seen}"; then GPIO_VERSION="`$PKG_CONFIG --silence-errors --modversion libgpiod 2>/dev/null`" if test "$?" != "0" -o -z "${GPIO_VERSION}"; then GPIO_VERSION="none" + else + nut_gpio_lib="libgpiod" fi AC_MSG_RESULT(${GPIO_VERSION} found) ], @@ -71,11 +74,13 @@ if test -z "${nut_have_gpio_seen}"; then dnl check if gpiod is usable AC_CHECK_HEADERS(gpiod.h, [nut_have_gpio=yes], [nut_have_gpio=no], [AC_INCLUDES_DEFAULT]) - AC_CHECK_FUNCS(gpiod_chip_open_by_name gpiod_chip_close, [], [nut_have_gpio=no]) + AC_CHECK_FUNCS(gpiod_chip_open_by_name gpiod_chip_close, [nut_gpio_lib="libgpiod"], [nut_have_gpio=no]) if test "${nut_have_gpio}" = "yes"; then LIBGPIO_CFLAGS="${CFLAGS}" LIBGPIO_LIBS="${LIBS}" + else + nut_gpio_lib="" fi dnl restore original CFLAGS and LIBS From c07179f60557c7035c168c78f2981c017e308aa8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 14:27:01 +0100 Subject: [PATCH 0549/1232] docs/configure.txt: update prereq note for GPIO drivers --- docs/configure.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/configure.txt b/docs/configure.txt index 8f3d78d609..253e4f8fbd 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -176,7 +176,8 @@ GPIO bus drivers Build and install GPIO drivers (default: auto-detect) -Note that on Linux you need to install libgpiod development package or files. +Note that on Linux you need to install libgpiod development package or files, +although usually it is part of linux-libc-dev or similar. Other platforms are not currently supported, but may be in the future. Modbus drivers From 5d7695c41d59599783233fb979f952b8fd51b621 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 15:22:32 +0100 Subject: [PATCH 0550/1232] docs/config-prereqs.txt: add installation of (lib)gpio(d)-dev(el) where feasible --- docs/config-prereqs.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 19233af448..a1911ba322 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -157,6 +157,7 @@ metadata about recently published package revisions: # NOTE: Some older Debian-like distributions, could ship "libcrypto-dev" # and/or "openssl-dev" instead of "libssl-dev" by its modern name +# and may lack a libgpiod2 + libgpiod-dev altogether :; apt-get install \ libcppunit-dev \ libssl-dev libnss3-dev \ @@ -164,6 +165,7 @@ metadata about recently published package revisions: libusb-dev libusb-1.0-0-dev \ libi2c-dev \ libmodbus-dev \ + libgpiod-dev \ libsnmp-dev \ libpowerman0-dev \ libfreeipmi-dev libipmimonitoring-dev \ @@ -350,6 +352,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. #?# is python-augeas needed? exists at least... #?# no (lib)i2c-devel ... #?# no (lib)ipmimonitoring-devel ... would "freeipmi-ipmidetectd" cut it at least for run-time? +#?# no (lib)gpio(d)-devel - starts with CentOS 8 (or extra repositories for later minor releases of CentOS 7) # 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... @@ -424,6 +427,8 @@ Install tools and prerequisites for NUT: freeipmi \ avahi +#?# no (lib)gpio(d) + :; pacman -S --needed \ lua51 From 0e01f3373b5935160eb7a12bb03afc776b6c5b14 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 15:30:41 +0100 Subject: [PATCH 0551/1232] NEWS, UPGRADING, docs/configure.txt: clarify that libgpiod is for Linux released after ~2018 --- NEWS | 4 ++-- UPGRADING | 4 ++-- docs/configure.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index d9a5f8031d..94293e47d4 100644 --- a/NEWS +++ b/NEWS @@ -141,8 +141,8 @@ https://github.com/networkupstools/nut/milestone/8 - GPIO drivers [#1855]: * Added a new category of drivers, using GPIO interface to locally connected - devices (currently limited to Linux libgpiod, but its architecture was - designed to later support more OSes with their equivalents - PRs welcome) + devices (currently limited to 2018+ Linux libgpiod, but its architecture + was designed to support more OSes with their equivalents - PRs welcome) * `generic_gpio_libgpiod` driver using `libgpiod` backend was added (defaults to be required on Linux, optional on other platforms) diff --git a/UPGRADING b/UPGRADING index 7c9cf4ddce..a6a09315af 100644 --- a/UPGRADING +++ b/UPGRADING @@ -70,8 +70,8 @@ Changes from 2.8.0 to 2.8.1 may impact packaging decisions on some distributions going forward [#1446] - GPIO category of drivers was added (`--with-gpio` configure script option) - - this may impact packaging decisions on some (currently Linux) distributions - going forward [#1855] + this may impact packaging decisions on some (currently Linux released 2018+) + distributions going forward [#1855] - An explicit `configure --with-nut-scanner` toggle was added, specifically so that build environments requesting `--with-all` but lacking `libltdl` diff --git a/docs/configure.txt b/docs/configure.txt index 253e4f8fbd..91f08ec669 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -176,8 +176,8 @@ GPIO bus drivers Build and install GPIO drivers (default: auto-detect) -Note that on Linux you need to install libgpiod development package or files, -although usually it is part of linux-libc-dev or similar. +Note that on Linux you need to install libgpiod library and development package +or files. This seems to be present in distributions released after roughly 2018. Other platforms are not currently supported, but may be in the future. Modbus drivers From b0ecbd1433a7d81755f71b47f33cd0f6c3755e59 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Mar 2023 15:33:23 +0100 Subject: [PATCH 0552/1232] configure.ac: do not require --with-gpio=yes for builds --with-all even on Linux: only the newer distros support the tech --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 11bc7e8ad7..5de4283d45 100644 --- a/configure.ac +++ b/configure.ac @@ -1176,7 +1176,7 @@ AC_ARG_WITH(drivers, dnl NOTE: Currently we only support a Linux libgpiod dnl backend for GPIO; eventually there could be more. case ${target_os} in - linux*) with_gpio="yes";; + linux*) with_gpio="auto";; dnl # TODO: Detect 2018+ distros? *) with_gpio="auto";; esac fi @@ -1371,7 +1371,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, linux_i2c (on Linux), macosx-ups (on MacOS), cgi, dev, avahi, nut-scanner, 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), macosx-ups (on MacOS), cgi, dev, avahi, nut-scanner, pynut]), [ if test -n "${withval}"; then dnl Note: we allow "no" as a positive value, because From 39e8d02965f4ce7336f50f765001b79e175c968f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 08:47:48 +0000 Subject: [PATCH 0553/1232] GitIgnore tests/gpiotest* artifacts --- tests/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/.gitignore b/tests/.gitignore index 9fa8deae00..fe7beea504 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,9 @@ /cppnit /cppnit.log /cppnit.trs +/gpiotest +/gpiotest.log +/gpiotest.trs /test-suite.log /selftest-rw/* /nutlogtest-nofail.sh From 1a791c40fd0d8000054b86bdd3a0869f8ff363f0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 11:12:51 +0000 Subject: [PATCH 0554/1232] drivers/generic_gpio*.h: move "extern struct gpioups_t *gpioupsfd" to generic_gpio_common.h --- drivers/generic_gpio_common.c | 2 +- drivers/generic_gpio_common.h | 2 ++ drivers/generic_gpio_libgpiod.h | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index 19ebd9cb20..e0a39b4448 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -25,7 +25,7 @@ #include "attribute.h" #include "generic_gpio_common.h" -struct gpioups_t *gpioupsfd=(struct gpioups_t *)NULL; +struct gpioups_t *gpioupsfd = (struct gpioups_t *)NULL; static struct gpioups_t *generic_gpio_open(const char *chipName); static void generic_gpio_close(struct gpioups_t *gpioupsfd); diff --git a/drivers/generic_gpio_common.h b/drivers/generic_gpio_common.h index 4a591bcc1f..6bbc3f1d96 100644 --- a/drivers/generic_gpio_common.h +++ b/drivers/generic_gpio_common.h @@ -61,6 +61,8 @@ typedef struct gpioups_t { struct rulesint_t **rules; } gpioups; +extern struct gpioups_t *gpioupsfd; + void gpio_open(struct gpioups_t *gpioupsfd); void gpio_get_lines_states(struct gpioups_t *gpioupsfd); void gpio_close(struct gpioups_t *gpioupsfd); diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h index 4725f170bc..43dd98dfda 100644 --- a/drivers/generic_gpio_libgpiod.h +++ b/drivers/generic_gpio_libgpiod.h @@ -27,8 +27,6 @@ #define DRIVER_NAME "GPIO UPS driver" #define DRIVER_VERSION "1.00" -extern struct gpioups_t *gpioupsfd; - typedef struct libgpiod_data_t { struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ From 17bacdf9cfb7eb3f7e2b3c1f0d264d031a88d72a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 11:13:35 +0000 Subject: [PATCH 0555/1232] drivers/generic_gpio_common.c: rename "(gpio)upsfd" method arguments to avoid shadowing global varnames --- drivers/generic_gpio_common.c | 170 +++++++++++++++++----------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index e0a39b4448..330f613719 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -55,35 +55,35 @@ static struct gpioups_t *generic_gpio_open(const char *chipName) { /* * release common data structures */ -static void generic_gpio_close(struct gpioups_t *gpioupsfd) { - if(gpioupsfd) { - if(gpioupsfd->upsLines) { - free(gpioupsfd->upsLines); +static void generic_gpio_close(struct gpioups_t *gpioupsfdlocal) { + if (gpioupsfdlocal) { + if (gpioupsfdlocal->upsLines) { + free(gpioupsfdlocal->upsLines); } - if(gpioupsfd->upsLinesStates) { - free(gpioupsfd->upsLinesStates); + if (gpioupsfdlocal->upsLinesStates) { + free(gpioupsfdlocal->upsLinesStates); } - if(gpioupsfd->rules) { + if (gpioupsfdlocal->rules) { int i; - for(i=0; irulesCount; i++) { - free(gpioupsfd->rules[i]); + for (i=0; i < gpioupsfdlocal->rulesCount; i++) { + free(gpioupsfdlocal->rules[i]); } } - free(gpioupsfd); - gpioupsfd=NULL; + free(gpioupsfdlocal); + gpioupsfdlocal = NULL; } } /* * add compiled subrules item to the array */ -static void add_rule_item(struct gpioups_t *upsfd, int newValue) { - int subCount = (upsfd->rules[upsfd->rulesCount-1]) ? upsfd->rules[upsfd->rulesCount-1]->subCount+1 : 1; - int itemSize = subCount*sizeof(upsfd->rules[0]->cRules[0])+sizeof(rulesint); +static 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); - upsfd->rules[upsfd->rulesCount-1] = xrealloc(upsfd->rules[upsfd->rulesCount-1], itemSize); - upsfd->rules[upsfd->rulesCount-1]->subCount = subCount; - upsfd->rules[upsfd->rulesCount-1]->cRules[subCount-1] = newValue; + upsfdlocal->rules[upsfdlocal->rulesCount-1] = xrealloc(upsfdlocal->rules[upsfdlocal->rulesCount-1], itemSize); + upsfdlocal->rules[upsfdlocal->rulesCount-1]->subCount = subCount; + upsfdlocal->rules[upsfdlocal->rulesCount-1]->cRules[subCount-1] = newValue; } /* @@ -122,7 +122,7 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { /* * split subrules and translate them to array of commands/line numbers */ -static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { +static void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesString) { /* statename=[^]line[&||[line]] */ char lexBuff[33]; int startPos = 0, endPos; @@ -150,11 +150,11 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { lexStatus=-1; } else { lexStatus = 1; - upsfd->rulesCount++; - upsfd->rules = xrealloc(upsfd->rules, (size_t)(sizeof(upsfd->rules[0])*upsfd->rulesCount)); - upsfd->rules[upsfd->rulesCount-1] = xcalloc(sizeof(rulesint), 1); - strncpy(upsfd->rules[upsfd->rulesCount-1]->stateName, (char *)(rulesString+startPos), endPos-startPos); - upsfd->rules[upsfd->rulesCount-1]->stateName[endPos-startPos] = 0; + upsfdlocal->rulesCount++; + upsfdlocal->rules = xrealloc(upsfdlocal->rules, (size_t)(sizeof(upsfdlocal->rules[0])*upsfdlocal->rulesCount)); + upsfdlocal->rules[upsfdlocal->rulesCount-1] = xcalloc(sizeof(rulesint), 1); + strncpy(upsfdlocal->rules[upsfdlocal->rulesCount-1]->stateName, (char *)(rulesString+startPos), endPos-startPos); + upsfdlocal->rules[upsfdlocal->rulesCount-1]->stateName[endPos-startPos] = 0; } break; @@ -169,10 +169,10 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { case 2: if(lexType == '^') { lexStatus = 3; - add_rule_item(upsfd, RULES_CMD_NOT); + add_rule_item(upsfdlocal, RULES_CMD_NOT); } else if(lexType == '0') { lexStatus = 4; - add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); + add_rule_item(upsfdlocal, atoi((char *)(rulesString+startPos))); } else { lexStatus = -1; } @@ -183,17 +183,17 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { lexStatus = -1; } else { lexStatus = 4; - add_rule_item(upsfd, atoi((char *)(rulesString+startPos))); + add_rule_item(upsfdlocal, atoi((char *)(rulesString+startPos))); } break; case 4: if(lexType == '&') { lexStatus = 2; - add_rule_item(upsfd, RULES_CMD_AND); + add_rule_item(upsfdlocal, RULES_CMD_AND); } else if(lexType == '|') { lexStatus = 2; - add_rule_item(upsfd, RULES_CMD_OR); + add_rule_item(upsfdlocal, RULES_CMD_OR); } else if(lexType == ';') { lexStatus = 0; @@ -214,88 +214,88 @@ static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString) { fatalx(LOG_ERR, "Line processing rule error at position %d", startPos); /* debug printout for extracted rules */ - upsdebugx(LOG_DEBUG, "rules count [%d]", upsfd->rulesCount); - for(i = 0; i < upsfd->rulesCount; i++) { + upsdebugx(LOG_DEBUG, "rules count [%d]", upsfdlocal->rulesCount); + for(i = 0; i < upsfdlocal->rulesCount; i++) { upsdebugx( LOG_DEBUG, "rule state name [%s], subcount %d", - upsfd->rules[i]->stateName, - upsfd->rules[i]->subCount + upsfdlocal->rules[i]->stateName, + upsfdlocal->rules[i]->subCount ); - for(j = 0; jrules[i]->subCount; j++) { + for(j = 0; jrules[i]->subCount; j++) { upsdebugx( LOG_DEBUG, "[%s] substate %d [%d]", - upsfd->rules[i]->stateName, + upsfdlocal->rules[i]->stateName, j, - upsfd->rules[i]->cRules[j] + upsfdlocal->rules[i]->cRules[j] ); } } /* get gpio lines used in rules, find max line number used to check with chip lines count*/ - upsfd->upsLinesCount = 0; - upsfd->upsMaxLine = 0; - for(i = 0; i < upsfd->rulesCount; i++) { - for(j = 0; j < upsfd->rules[i]->subCount; j++) { + upsfdlocal->upsLinesCount = 0; + upsfdlocal->upsMaxLine = 0; + for(i = 0; i < upsfdlocal->rulesCount; i++) { + for(j = 0; j < upsfdlocal->rules[i]->subCount; j++) { int pinOnList = 0; - for(k = 0; k < upsfd->upsLinesCount && !pinOnList; k++) { - if(upsfd->upsLines[k] == upsfd->rules[i]->cRules[j]) { + for(k = 0; k < upsfdlocal->upsLinesCount && !pinOnList; k++) { + if(upsfdlocal->upsLines[k] == upsfdlocal->rules[i]->cRules[j]) { pinOnList = 1; } } if(!pinOnList) { - if(upsfd->rules[i]->cRules[j] >= 0) { - upsfd->upsLinesCount++; - upsfd->upsLines = xrealloc(upsfd->upsLines, sizeof(upsfd->upsLines[0])*upsfd->upsLinesCount); - upsfd->upsLines[upsfd->upsLinesCount-1] = upsfd->rules[i]->cRules[j]; - if(upsfd->upsLines[upsfd->upsLinesCount-1] > upsfd->upsMaxLine) { - upsfd->upsMaxLine = upsfd->upsLines[upsfd->upsLinesCount-1]; + if(upsfdlocal->rules[i]->cRules[j] >= 0) { + upsfdlocal->upsLinesCount++; + upsfdlocal->upsLines = 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]; } } } } } - upsdebugx(LOG_DEBUG, "UPS line count = %d", upsfd->upsLinesCount); - for(i = 0; i < upsfd->upsLinesCount; i++) { - upsdebugx(LOG_DEBUG, "UPS line%d number %d", i, upsfd->upsLines[i]); + upsdebugx(LOG_DEBUG, "UPS line count = %d", upsfdlocal->upsLinesCount); + for(i = 0; i < upsfdlocal->upsLinesCount; i++) { + upsdebugx(LOG_DEBUG, "UPS line%d number %d", i, upsfdlocal->upsLines[i]); } /* transform lines to indexes for easier state calculation */ - tranformationDelta = upsfd->upsMaxLine - RULES_CMD_LAST + 1; - for(i = 0; i < upsfd->rulesCount; i++) { - for(j = 0; j < upsfd->rules[i]->subCount; j++) { - if(upsfd->rules[i]->cRules[j] >= 0) { - upsfd->rules[i]->cRules[j] -= tranformationDelta; + tranformationDelta = upsfdlocal->upsMaxLine - RULES_CMD_LAST + 1; + for(i = 0; i < upsfdlocal->rulesCount; i++) { + for(j = 0; j < upsfdlocal->rules[i]->subCount; j++) { + if(upsfdlocal->rules[i]->cRules[j] >= 0) { + upsfdlocal->rules[i]->cRules[j] -= tranformationDelta; } } } - for(k = 0; k < upsfd->upsLinesCount; k++) { - for(i = 0; i < upsfd->rulesCount; i++) { - for(j = 0; j < upsfd->rules[i]->subCount; j++) { - if((upsfd->rules[i]->cRules[j] + tranformationDelta) == upsfd->upsLines[k]) { - upsfd->rules[i]->cRules[j] = k; + for(k = 0; k < upsfdlocal->upsLinesCount; k++) { + for(i = 0; i < upsfdlocal->rulesCount; i++) { + for(j = 0; j < upsfdlocal->rules[i]->subCount; j++) { + if((upsfdlocal->rules[i]->cRules[j] + tranformationDelta) == upsfdlocal->upsLines[k]) { + upsfdlocal->rules[i]->cRules[j] = k; } } } } /* debug printout of transformed lines numbers */ - upsdebugx(LOG_DEBUG, "rules count [%d] translated", upsfd->rulesCount); - for(i = 0; i < upsfd->rulesCount; i++) { + upsdebugx(LOG_DEBUG, "rules count [%d] translated", upsfdlocal->rulesCount); + for(i = 0; i < upsfdlocal->rulesCount; i++) { upsdebugx( LOG_DEBUG, "rule state name [%s], subcount %d translated", - upsfd->rules[i]->stateName, - upsfd->rules[i]->subCount + upsfdlocal->rules[i]->stateName, + upsfdlocal->rules[i]->subCount ); - for(j = 0; j < upsfd->rules[i]->subCount; j++) { + for(j = 0; j < upsfdlocal->rules[i]->subCount; j++) { upsdebugx( LOG_DEBUG, "[%s] substate %d [%d]", - upsfd->rules[i]->stateName, j, - upsfd->rules[i]->cRules[j] + upsfdlocal->rules[i]->stateName, j, + upsfdlocal->rules[i]->cRules[j] ); } } @@ -340,7 +340,7 @@ static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, in * set ups state according to rules, do adjustments for CHRG/DISCHRG * and battery charge states */ -static void update_ups_states(struct gpioups_t *gpioupsfd) { +static void update_ups_states(struct gpioups_t *gpioupsfdlocal) { int batLow = 0; int bypass = 0; int chargerStatusSet = 0; @@ -348,39 +348,39 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { status_init(); - for(ruleNo = 0; ruleNo < gpioupsfd->rulesCount; ruleNo++) { - gpioupsfd->rules[ruleNo]->currVal = + for(ruleNo = 0; ruleNo < gpioupsfdlocal->rulesCount; ruleNo++) { + gpioupsfdlocal->rules[ruleNo]->currVal = calc_rule_states( - gpioupsfd->upsLinesStates, - gpioupsfd->rules[ruleNo]->cRules, - gpioupsfd->rules[ruleNo]->subCount, 0 + gpioupsfdlocal->upsLinesStates, + gpioupsfdlocal->rules[ruleNo]->cRules, + gpioupsfdlocal->rules[ruleNo]->subCount, 0 ); - if(gpioupsfd->rules[ruleNo]->currVal) { - status_set(gpioupsfd->rules[ruleNo]->stateName); + if(gpioupsfdlocal->rules[ruleNo]->currVal) { + status_set(gpioupsfdlocal->rules[ruleNo]->stateName); - if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "CHRG")) { + if(!strcmp(gpioupsfdlocal->rules[ruleNo]->stateName, "CHRG")) { dstate_setinfo("battery.charger.status", "%s", "charging"); chargerStatusSet++; } - if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "DISCHRG")) { + if(!strcmp(gpioupsfdlocal->rules[ruleNo]->stateName, "DISCHRG")) { dstate_setinfo("battery.charger.status", "%s", "discharging"); chargerStatusSet++; } - if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "LB")) { + if(!strcmp(gpioupsfdlocal->rules[ruleNo]->stateName, "LB")) { batLow = 1; } - if(!strcmp(gpioupsfd->rules[ruleNo]->stateName, "BYPASS")) { + if(!strcmp(gpioupsfdlocal->rules[ruleNo]->stateName, "BYPASS")) { bypass = 1; } } - if(gpioupsfd->aInfoAvailable && - gpioupsfd->rules[ruleNo]->archVal != gpioupsfd->rules[ruleNo]->currVal) { + if(gpioupsfdlocal->aInfoAvailable && + gpioupsfdlocal->rules[ruleNo]->archVal != gpioupsfdlocal->rules[ruleNo]->currVal) { upslogx(LOG_WARNING, "UPS state [%s] changed to %d", - gpioupsfd->rules[ruleNo]->stateName, - gpioupsfd->rules[ruleNo]->currVal + gpioupsfdlocal->rules[ruleNo]->stateName, + gpioupsfdlocal->rules[ruleNo]->currVal ); } - gpioupsfd->rules[ruleNo]->archVal = gpioupsfd->rules[ruleNo]->currVal; + gpioupsfdlocal->rules[ruleNo]->archVal = gpioupsfdlocal->rules[ruleNo]->currVal; } if(chargerStatusSet <= 0) { @@ -399,7 +399,7 @@ static void update_ups_states(struct gpioups_t *gpioupsfd) { dstate_delinfo("battery.charge"); } - gpioupsfd->aInfoAvailable = 1; + gpioupsfdlocal->aInfoAvailable = 1; status_commit(); } From 182d5b68b75df0ca506820891b71f6b5c8f146dc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 11:15:54 +0000 Subject: [PATCH 0556/1232] drivers/generic_gpio_libgpiod.c: rename "(gpio)upsfd" method arguments to avoid shadowing global varnames --- drivers/generic_gpio_libgpiod.c | 80 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 8927d636a8..d5445d0414 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -69,15 +69,15 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner); * reserve GPIO lines as per run options and inner parameter: do reservation once * or per each status read */ -static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); - upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions 0x%x, inner %d", gpioupsfd->runOptions, inner); +static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfdlocal, int inner) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfdlocal->lib_data); + upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod runOptions 0x%x, inner %d", gpioupsfdlocal->runOptions, inner); - if(((gpioupsfd->runOptions&ROPT_REQRES) != 0) == inner) { + if(((gpioupsfdlocal->runOptions&ROPT_REQRES) != 0) == inner) { struct gpiod_line_request_config config; int gpioRc; config.consumer=upsdrv_info.name; - if(gpioupsfd->runOptions&ROPT_EVMODE) { + if(gpioupsfdlocal->runOptions&ROPT_EVMODE) { config.request_type = GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES; upsdebugx(LOG_DEBUG, "reserve_lines_libgpiod GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES"); } else { @@ -104,37 +104,37 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfd, int inner) { * allocate memeory for libary, open gpiochip * and check lines numbers validity - consistency with h/w chip */ -void gpio_open(struct gpioups_t *gpioupsfd) { +void gpio_open(struct gpioups_t *gpioupsfdlocal) { struct libgpiod_data_t *libgpiod_data = xcalloc(sizeof(struct libgpiod_data_t),1); - gpioupsfd->lib_data = libgpiod_data; + gpioupsfdlocal->lib_data = libgpiod_data; - libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfd->chipName); + libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfdlocal->chipName); if(!libgpiod_data->gpioChipHandle) fatal_with_errno( LOG_ERR, "Could not open GPIO chip [%s], check chips presence and/or access rights", - gpioupsfd->chipName + gpioupsfdlocal->chipName ); else { int gpioRc; - upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfd->chipName); - gpioupsfd->chipLinesCount = gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); - upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfd->chipLinesCount, gpioupsfd->chipName); - if(gpioupsfd->chipLinesCountupsMaxLine) { + upslogx(LOG_NOTICE, "GPIO chip [%s] opened", gpioupsfdlocal->chipName); + gpioupsfdlocal->chipLinesCount = gpiod_chip_num_lines(libgpiod_data->gpioChipHandle); + upslogx(LOG_NOTICE, "Find %d lines on GPIO chip [%s]", gpioupsfdlocal->chipLinesCount, gpioupsfdlocal->chipName); + if(gpioupsfdlocal->chipLinesCountupsMaxLine) { gpiod_chip_close(libgpiod_data->gpioChipHandle); fatalx( LOG_ERR, "GPIO chip lines count %d smaller than UPS line number used (%d)", - gpioupsfd->chipLinesCount, - gpioupsfd->upsMaxLine + gpioupsfdlocal->chipLinesCount, + gpioupsfdlocal->upsMaxLine ); } gpiod_line_bulk_init(&libgpiod_data->gpioLines); gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); gpioRc = gpiod_chip_get_lines( libgpiod_data->gpioChipHandle, - (unsigned int *)gpioupsfd->upsLines, - gpioupsfd->upsLinesCount, + (unsigned int *)gpioupsfdlocal->upsLines, + gpioupsfdlocal->upsLinesCount, &libgpiod_data->gpioLines ); if(gpioRc) @@ -144,22 +144,22 @@ void gpio_open(struct gpioups_t *gpioupsfd) { gpioRc ); upsdebugx(LOG_DEBUG, "GPIO gpiod_chip_get_lines return code %d", gpioRc); - reserve_lines_libgpiod(gpioupsfd, 0); + reserve_lines_libgpiod(gpioupsfdlocal, 0); } } /* * close gpiochip and release allocated memory */ -void gpio_close(struct gpioups_t *gpioupsfd) { - if(gpioupsfd) { - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); +void gpio_close(struct gpioups_t *gpioupsfdlocal) { + if(gpioupsfdlocal) { + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfdlocal->lib_data); if(libgpiod_data) { if(libgpiod_data->gpioChipHandle) { gpiod_chip_close(libgpiod_data->gpioChipHandle); } - free(gpioupsfd->lib_data); - gpioupsfd->lib_data = NULL; + free(gpioupsfdlocal->lib_data); + gpioupsfdlocal->lib_data = NULL; } } } @@ -167,31 +167,31 @@ void gpio_close(struct gpioups_t *gpioupsfd) { /* * get GPIO line states for all needed lines */ -void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { +void gpio_get_lines_states(struct gpioups_t *gpioupsfdlocal) { int i; int gpioRc; - struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfd->lib_data); + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)(gpioupsfdlocal->lib_data); - reserve_lines_libgpiod(gpioupsfd, 1); - if(gpioupsfd->runOptions&ROPT_EVMODE) { + reserve_lines_libgpiod(gpioupsfdlocal, 1); + if(gpioupsfdlocal->runOptions&ROPT_EVMODE) { struct timespec timeoutLong = {1,0}; struct gpiod_line_event event; int monRes; upsdebugx( LOG_DEBUG, "gpio_get_lines_states_libgpiod initial %d, timeout %ld", - gpioupsfd->initial, + gpioupsfdlocal->initial, timeoutLong.tv_sec ); - if(gpioupsfd->initial) { + if(gpioupsfdlocal->initial) { timeoutLong.tv_sec = 35; } else { - gpioupsfd->initial = 1; + gpioupsfdlocal->initial = 1; } upsdebugx( LOG_DEBUG, "gpio_get_lines_states_libgpiod initial %d, timeout %ld", - gpioupsfd->initial, + gpioupsfdlocal->initial, timeoutLong.tv_sec ); gpiod_line_bulk_init(&libgpiod_data->gpioEventLines); @@ -208,11 +208,11 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { ); if(monRes==1) { int num_lines = (int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); - int i; - for(i=0; igpioEventLines, - i + j ); int eventRc=gpiod_line_event_read(eLine, &event); unsigned int lineOffset = gpiod_line_offset(eLine); @@ -227,12 +227,12 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { } } } - for(i=0; i < gpioupsfd->upsLinesCount; i++) { - gpioupsfd->upsLinesStates[i] = -1; + for(i=0; i < gpioupsfdlocal->upsLinesCount; i++) { + gpioupsfdlocal->upsLinesStates[i] = -1; } gpioRc=gpiod_line_get_value_bulk( &libgpiod_data->gpioLines, - gpioupsfd->upsLinesStates + gpioupsfdlocal->upsLinesStates ); if (gpioRc < 0) @@ -244,16 +244,16 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfd) { gpioRc ); - for(i=0; i < gpioupsfd->upsLinesCount; i++) { + for(i=0; i < gpioupsfdlocal->upsLinesCount; i++) { upsdebugx( LOG_DEBUG, "Line%d state = %d", i, - gpioupsfd->upsLinesStates[i] + gpioupsfdlocal->upsLinesStates[i] ); } - if(gpioupsfd->runOptions&ROPT_REQRES) { + if(gpioupsfdlocal->runOptions&ROPT_REQRES) { gpiod_line_release_bulk(&libgpiod_data->gpioLines); } } From 08e4ed44e45c34c4774e93a730e14939786dc6b5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 11:29:04 +0000 Subject: [PATCH 0557/1232] drivers/Makefile.am: relocate "endif" lines so sources of tests are always redistributed --- tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 9cb85e5044..a2377901da 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,20 +50,20 @@ hidparser.c: $(top_srcdir)/drivers/hidparser.c if WITH_USB TESTS += getvaluetest +endif getvaluetest_SOURCES = getvaluetest.c nodist_getvaluetest_SOURCES = hidparser.c # Pull the right include path for chosen libusb version: getvaluetest_CFLAGS = $(AM_CFLAGS) $(LIBUSB_CFLAGS) getvaluetest_LDADD = $(top_builddir)/common/libcommon.la -endif if WITH_GPIO TESTS += gpiotest +endif gpiotest_SOURCES = generic_gpio_utest.c gpiotest_LDADD = $(top_builddir)/common/libcommon.la -endif # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/common/libcommon.la: dummy From da0dbdb5ba8af710d334e7b37180b6a62cd05834 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 11:30:45 +0000 Subject: [PATCH 0558/1232] Introduce tests/generic_gpio_utest.h --- tests/Makefile.am | 1 + tests/generic_gpio_liblocal.c | 6 +++--- tests/generic_gpio_utest.c | 1 + tests/generic_gpio_utest.h | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/generic_gpio_utest.h diff --git a/tests/Makefile.am b/tests/Makefile.am index a2377901da..4d24109495 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,6 +64,7 @@ endif gpiotest_SOURCES = generic_gpio_utest.c gpiotest_LDADD = $(top_builddir)/common/libcommon.la +EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/common/libcommon.la: dummy diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c index ad9e5cbf74..ae571d8d7a 100644 --- a/tests/generic_gpio_liblocal.c +++ b/tests/generic_gpio_liblocal.c @@ -23,8 +23,7 @@ #include "common.h" #include #include -#include "generic_gpio_common.h" -#include "generic_gpio_libgpiod.h" +#include "generic_gpio_utest.h" static char chipName[16]; static unsigned int num_lines=0; @@ -45,6 +44,7 @@ unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { 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) { @@ -68,7 +68,7 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, static int gStatus = 0; static int errReqFor_line_get_value_bulk=0; -void setNextLinesReadToFail() { +void setNextLinesReadToFail(void) { errReqFor_line_get_value_bulk=1; } diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 370739ed61..f714fc4a0d 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -23,6 +23,7 @@ #include "config.h" #include "main.h" #include "attribute.h" +#include "generic_gpio_utest.h" #include "generic_gpio_common.c" #include diff --git a/tests/generic_gpio_utest.h b/tests/generic_gpio_utest.h new file mode 100644 index 0000000000..9ad884319d --- /dev/null +++ b/tests/generic_gpio_utest.h @@ -0,0 +1,35 @@ +/* generic_gpio_utest.h - unit tests for gpiod based NUT driver definitions + * for GPIO attached UPS devices + * + * Copyright (C) + * 2023 Modris Berzonis + * 2023 Jim Klimov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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 GENERIC_GPIO_UTEST_H +#define GENERIC_GPIO_UTEST_H + +#include "generic_gpio_common.h" +#include "generic_gpio_libgpiod.h" + +void setNextLinesReadToFail(void); +void getWithoutUnderscores(char *var); +int get_test_status(struct gpioups_t *result, int on_fail_path); + +#endif /* GENERIC_GPIO_UTEST_H */ From 5ada877a1baf42b6ea4859f9f56901db4d0ba6d4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 12:37:06 +0100 Subject: [PATCH 0559/1232] drivers/generic_gpio_libgpiod.c: rename "num_lines" to avoid global varname clash (in tests) --- drivers/generic_gpio_libgpiod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index d5445d0414..76d4b8945e 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -207,9 +207,9 @@ void gpio_get_lines_states(struct gpioups_t *gpioupsfdlocal) { timeoutLong.tv_sec ); if(monRes==1) { - int num_lines = (int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); + int num_lines_local = (int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines); int j; - for(j=0; jgpioEventLines, j From b62d398443444abadeb7384b0c6c7c5673f49e95 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 12:42:24 +0100 Subject: [PATCH 0560/1232] Define NUT_GPIO_SUBTYPEBUF and NUT_GPIO_CHIPNAMEBUF for consistency, avoid local/global varname clashes for chipName --- drivers/generic_gpio_common.h | 4 ++++ tests/generic_gpio_liblocal.c | 2 +- tests/generic_gpio_utest.c | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/generic_gpio_common.h b/drivers/generic_gpio_common.h index 6bbc3f1d96..a0811756fb 100644 --- a/drivers/generic_gpio_common.h +++ b/drivers/generic_gpio_common.h @@ -38,6 +38,10 @@ #define ROPT_REQRES 0x00000001 /* reserve GPIO lines only during request processing */ #define ROPT_EVMODE 0x00000002 /* event driven run */ +/* buffer size for chipName arrays */ +#define NUT_GPIO_CHIPNAMEBUF 32 +#define NUT_GPIO_SUBTYPEBUF 16 + typedef struct rulesint_t { /* structure to store processed rules configuration per each state */ char stateName[12]; /* NUT state name for rules in cRules */ int archVal; /* previous state value */ diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c index ae571d8d7a..d8ad77074a 100644 --- a/tests/generic_gpio_liblocal.c +++ b/tests/generic_gpio_liblocal.c @@ -25,7 +25,7 @@ #include #include "generic_gpio_utest.h" -static char chipName[16]; +static char chipName[NUT_GPIO_CHIPNAMEBUF]; static unsigned int num_lines=0; struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index f714fc4a0d..91665fbdc5 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -253,11 +253,11 @@ int main(int argc, char **argv) { vartab_free(); vartab_h = NULL; } if(!strcmp(testType, "library")) { - char chipName[32]; + char chipNameLocal[NUT_GPIO_CHIPNAMEBUF]; int expecting_failure; - char subType[16]; + char subType[NUT_GPIO_SUBTYPEBUF]; fEof=fscanf(testData, "%d", &expecting_failure); - fEof=fscanf(testData, "%s", chipName); + fEof=fscanf(testData, "%s", chipNameLocal); fEof=fscanf(testData, "%s", subType); jmp_result = setjmp(env_buffer); int failed=expecting_failure; @@ -266,7 +266,7 @@ int main(int argc, char **argv) { upsdrv_cleanup(); } else { if(expecting_failure) failed=1; - device_path = chipName; + device_path = chipNameLocal; if(strcmp(subType, "initinfo") || !expecting_failure) { addvar(VAR_VALUE, "rules", ""); storeval("rules", rules); @@ -299,7 +299,7 @@ int main(int argc, char **argv) { upsdrv_cleanup(); } printf("%s %s %s test rule %d [%s] %s %d\n", - pass_fail[failed], testType, subType, i, rules, chipName, expecting_failure); + pass_fail[failed], testType, subType, i, rules, chipNameLocal, expecting_failure); if(!failed) { cases_passed++; } else { From 6c4cef6e9d47d7397528e2550cb4292a053b1ccb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 12:48:35 +0100 Subject: [PATCH 0561/1232] drivers/dstate.c: sock_fail(): rename "struct passwd *user" to avoid clash with global varname in main.c (due to tests/generic_gpio_utest.c construction) --- drivers/dstate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index b0a72dccdd..b6706458ea 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -65,7 +65,7 @@ static void sock_fail(const char *fn) static void sock_fail(const char *fn) { int sockerr; - struct passwd *user; + struct passwd *pwuser; /* save this so it doesn't get overwritten */ sockerr = errno; @@ -75,9 +75,9 @@ static void sock_fail(const char *fn) printf("\nFatal error: unable to create listener socket\n\n"); printf("bind %s failed: %s\n", fn, strerror(sockerr)); - user = getpwuid(getuid()); + pwuser = getpwuid(getuid()); - if (!user) { + if (!pwuser) { fatal_with_errno(EXIT_FAILURE, "getpwuid"); } @@ -86,7 +86,7 @@ static void sock_fail(const char *fn) { case EACCES: printf("\nCurrent user: %s (UID %d)\n\n", - user->pw_name, (int)user->pw_uid); + pwuser->pw_name, (int)pwuser->pw_uid); printf("Things to try:\n\n"); printf(" - set different owners or permissions on %s\n\n", From e8e2c075abb8c8146c18bd055f2b893816dd2f85 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 12:49:03 +0100 Subject: [PATCH 0562/1232] tests/generic_gpio_utest.c: add a declaration of ignore() to override the original main() from included main.c --- tests/generic_gpio_utest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 91665fbdc5..1e22b17e30 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -34,6 +34,7 @@ #include #define main ignore +int ignore(int argc, char **argv); #include "main.c" #undef main #include "dstate.c" From bb45620acc93864971745eabea4a6a197ba008c1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 12:54:25 +0100 Subject: [PATCH 0563/1232] tests/Makefile.am: refer to "tests/" as include-dir for gpiotest --- tests/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile.am b/tests/Makefile.am index 4d24109495..225d859789 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,6 +64,7 @@ endif gpiotest_SOURCES = generic_gpio_utest.c gpiotest_LDADD = $(top_builddir)/common/libcommon.la +gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h # Make sure out-of-dir dependencies exist (especially when dev-building parts): From e0afb4227b5304347db51e12857e78ed9165c0f4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 13:32:39 +0100 Subject: [PATCH 0564/1232] tests/generic_gpio_utest.c, tests/Makefile.am: EXTRA_DIST and use for out-of-tree builds the generic_gpio_test.txt resource file --- tests/Makefile.am | 2 +- tests/generic_gpio_utest.c | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 225d859789..bfc88d77d0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -65,7 +65,7 @@ endif gpiotest_SOURCES = generic_gpio_utest.c gpiotest_LDADD = $(top_builddir)/common/libcommon.la gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h +EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h generic_gpio_test.txt # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/common/libcommon.la: dummy diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 1e22b17e30..fd266c4dcd 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -146,15 +146,39 @@ int main(int argc, char **argv) { int jmp_result; char rules[128]; char testType[128]; - char *testDescFileName="./generic_gpio_test.txt"; + char testDescFileNameBuf[LARGEBUF]; + char *testDescFileName="generic_gpio_test.txt"; + if(argc==2) { testDescFileName=argv[1]; } + testData = fopen (testDescFileName, "r"); if(!testData) { - done = 1; - printf("failed to open test description file %s\n", testDescFileName); - exit(EXIT_FAILURE); + if (!strchr(testDescFileName, '/')) { + /* "srcdir" may be set by automake test harness, see + * https://www.gnu.org/software/automake/manual/1.12.2/html_node/Scripts_002dbased-Testsuites.html + */ + char *testDescFileDir = getenv("srcdir"); + if (testDescFileDir) { + printf("failed to open test description file %s " + "in current working directory, " + "retrying with srcdir %s\n", + testDescFileName, testDescFileDir); + if (snprintf(testDescFileNameBuf, sizeof(testDescFileNameBuf), "%s/%s", + testDescFileDir, testDescFileName) > 0 + ) { + testDescFileName = testDescFileNameBuf; + testData = fopen (testDescFileName, "r"); + } + } + } + + if(!testData) { + done = 1; + printf("failed to open test description file %s\n", testDescFileName); + exit(EXIT_FAILURE); + } } cases_passed=0; From a2c4c28030fe784f99ccf6ef83a810ad892f6ad6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 14:49:41 +0100 Subject: [PATCH 0565/1232] drivers/main.{c,h} drivers/Makefile.am: introduce libdummy_mockdrv.la (and DRIVERS_MAIN_WITHOUT_MAIN) --- drivers/Makefile.am | 8 ++++++++ drivers/main.c | 42 ++++++++++++++++++++++++++++++++++++------ drivers/main.h | 9 +++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index ec16ee8aa6..d6f4636223 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -369,6 +369,14 @@ libdummy_la_LDFLAGS = -no-undefined -static libdummy_serial_la_SOURCES = serial.c libdummy_serial_la_LDFLAGS = -no-undefined -static +# The libdummy_mockdrv.la is used for unit-tests to mock a driver +# with near-production codebase but without its standard main(). +# Otherwise, also not meant to be installed. +EXTRA_LTLIBRARIES += libdummy_mockdrv.la +libdummy_mockdrv_la_SOURCES = main.c dstate.c +libdummy_mockdrv_la_CFLAGS = $(AM_CFLAGS) -DDRIVERS_MAIN_WITHOUT_MAIN=1 +libdummy_mockdrv_la_LDFLAGS = -static $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la + dummy: CLEANFILES = $(EXTRA_LTLIBRARIES) $(EXTRA_PROGRAMS) diff --git a/drivers/main.c b/drivers/main.c index 02ba6cdfac..250b811200 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -56,7 +56,10 @@ int do_synchronous = -1; /* for detecting -a values that don't match anything */ static int upsname_found = 0; -static vartab_t *vartab_h = NULL; +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +vartab_t *vartab_h = NULL; /* variables possibly set by the global part of ups.conf * user and group may be set globally or per-driver @@ -68,6 +71,7 @@ static int user_from_cmdline = 0, group_from_cmdline = 0; /* signal handling */ int exit_flag = 0; +#ifndef DRIVERS_MAIN_WITHOUT_MAIN /* should this driver instance go to background (default) * or stay foregrounded (default if -D/-d options are set on * command line)? @@ -78,6 +82,7 @@ int exit_flag = 0; * 1 User required to background even if with -D or dump_mode */ static int background_flag = -1; +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ /* Users can pass a -D[...] option to enable debugging. * For the service tracing purposes, also the ups.conf @@ -89,9 +94,11 @@ static int background_flag = -1; static int nut_debug_level_global = -1; static int nut_debug_level_driver = -1; +#ifndef DRIVERS_MAIN_WITHOUT_MAIN /* everything else */ static char *pidfn = NULL; static int dump_data = 0; /* Store the update_count requested */ +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ /* print the driver banner */ void upsdrv_banner (void) @@ -116,6 +123,7 @@ void upsdrv_banner (void) } } +#ifndef DRIVERS_MAIN_WITHOUT_MAIN /* power down the attached load immediately */ static void forceshutdown(void) __attribute__((noreturn)); @@ -182,9 +190,13 @@ static void help_msg(void) upsdrv_help(); } +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ /* store these in dstate as driver.(parameter|flag) */ -static void dparam_setinfo(const char *var, const char *val) +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void dparam_setinfo(const char *var, const char *val) { char vtmp[SMALLBUF]; @@ -202,7 +214,10 @@ static void dparam_setinfo(const char *var, const char *val) } /* cram var [= ] data into storage */ -static void storeval(const char *var, char *val) +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void storeval(const char *var, char *val) { vartab_t *tmp, *last; @@ -566,6 +581,7 @@ void do_upsconf_args(char *confupsname, char *var, char *val) storeval(var, val); } +#ifndef DRIVERS_MAIN_WITHOUT_MAIN /* split -x foo=bar into 'foo' and 'bar' */ static void splitxarg(char *inbuf) { @@ -614,8 +630,12 @@ static void listxarg(void) tmp = tmp->next; } } +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ -static void vartab_free(void) +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void vartab_free(void) { vartab_t *tmp, *next; @@ -633,6 +653,7 @@ static void vartab_free(void) } } +#ifndef DRIVERS_MAIN_WITHOUT_MAIN static void exit_upsdrv_cleanup(void) { dstate_setinfo("driver.state", "cleanup.upsdrv"); @@ -667,6 +688,7 @@ static void exit_cleanup(void) } #endif } +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ void set_exit_flag(int sig) { @@ -674,7 +696,10 @@ void set_exit_flag(int sig) } #ifndef WIN32 -static void setup_signals(void) +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void setup_signals(void) { struct sigaction sa; @@ -697,8 +722,12 @@ static void setup_signals(void) sigaction(SIGHUP, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); } -#endif +#endif /* WIN32*/ +/* This source file is used in some unit tests to mock realistic driver + * behavior - using a production driver skeleton, but their own main(). + */ +#ifndef DRIVERS_MAIN_WITHOUT_MAIN int main(int argc, char **argv) { struct passwd *new_uid = NULL; @@ -1237,3 +1266,4 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ diff --git a/drivers/main.h b/drivers/main.h index 0998d5daa0..b9583eef2c 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -82,4 +82,13 @@ typedef struct upsdrv_info_s { /* public driver information from the driver file */ extern upsdrv_info_t upsdrv_info; +/* functions and data possibly used via libdummy_mockdrv.la for unit-tests */ +#ifdef DRIVERS_MAIN_WITHOUT_MAIN +extern vartab_t *vartab_h; +void dparam_setinfo(const char *var, const char *val); +void storeval(const char *var, char *val); +void vartab_free(void); +void setup_signals(void); +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ + #endif /* NUT_MAIN_H_SEEN */ From 466bcea7567ad27e7b16e869e96b2a28bbd43847 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 14:51:11 +0100 Subject: [PATCH 0566/1232] tests/generic_gpio_utest.c, tests/Makefile.am: avoid sourcing "main.c" and "dstate.c" right into test code --- tests/Makefile.am | 5 +++-- tests/generic_gpio_utest.c | 6 +----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index bfc88d77d0..6339f33c86 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,11 +63,12 @@ TESTS += gpiotest endif gpiotest_SOURCES = generic_gpio_utest.c -gpiotest_LDADD = $(top_builddir)/common/libcommon.la -gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests +gpiotest_LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/drivers/libdummy_mockdrv.la +gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h generic_gpio_test.txt # Make sure out-of-dir dependencies exist (especially when dev-building parts): +$(top_builddir)/drivers/libdummy_mockdrv.la \ $(top_builddir)/common/libcommon.la: dummy @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index fd266c4dcd..3b159c196e 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -33,11 +33,7 @@ #include #include -#define main ignore -int ignore(int argc, char **argv); -#include "main.c" -#undef main -#include "dstate.c" +#include "dstate.h" extern struct gpioups_t *gpioupsfd; From 3d15d607afde96fcce1f43cea46f7c0f3748cc03 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 15:01:02 +0100 Subject: [PATCH 0567/1232] tests/generic_gpio_utest.c, tests/Makefile.am: avoid "include generic_gpio_common.c generic_gpio_liblocal.c generic_gpio_libgpiod.c" in test code --- drivers/generic_gpio_common.c | 76 ++++++++++++++++++++++++++++------- drivers/generic_gpio_common.h | 11 +++++ tests/Makefile.am | 3 +- tests/generic_gpio_utest.c | 9 +---- 4 files changed, 77 insertions(+), 22 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index 330f613719..6bfd8c212e 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -27,18 +27,48 @@ struct gpioups_t *gpioupsfd = (struct gpioups_t *)NULL; -static struct gpioups_t *generic_gpio_open(const char *chipName); -static void generic_gpio_close(struct gpioups_t *gpioupsfd); -static void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString); -static void add_rule_item(struct gpioups_t *upsfd, int newValue); -static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); -static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex); -static void update_ups_states(struct gpioups_t *gpioupsfd); +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +struct gpioups_t *generic_gpio_open(const char *chipName); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void generic_gpio_close(struct gpioups_t *gpioupsfd); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void add_rule_item(struct gpioups_t *upsfd, int newValue); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex); + +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void update_ups_states(struct gpioups_t *gpioupsfd); /* * allocate common data structures and process/check rules */ -static struct gpioups_t *generic_gpio_open(const char *chipName) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +struct gpioups_t *generic_gpio_open(const char *chipName) { struct gpioups_t *upsfdlocal=xcalloc(sizeof(*upsfdlocal),1); upsfdlocal->runOptions=0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ upsfdlocal->chipName=chipName; @@ -55,7 +85,10 @@ static struct gpioups_t *generic_gpio_open(const char *chipName) { /* * release common data structures */ -static void generic_gpio_close(struct gpioups_t *gpioupsfdlocal) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void generic_gpio_close(struct gpioups_t *gpioupsfdlocal) { if (gpioupsfdlocal) { if (gpioupsfdlocal->upsLines) { free(gpioupsfdlocal->upsLines); @@ -77,7 +110,10 @@ static void generic_gpio_close(struct gpioups_t *gpioupsfdlocal) { /* * add compiled subrules item to the array */ -static void add_rule_item(struct gpioups_t *upsfdlocal, int newValue) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +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); @@ -91,7 +127,10 @@ static void add_rule_item(struct gpioups_t *upsfdlocal, int newValue) { * logical commands ^ , & , | , state names - several ascii characters matching NUT states, * and several numbers to denote GPIO chip lines to read statuses */ -static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { static unsigned char lexType[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 0x10 */ @@ -122,7 +161,10 @@ static int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos) { /* * split subrules and translate them to array of commands/line numbers */ -static void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesString) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesString) { /* statename=[^]line[&||[line]] */ char lexBuff[33]; int startPos = 0, endPos; @@ -304,7 +346,10 @@ static void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesStri /* * calculate state rule value based on GPIO line values */ -static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex) { int ruleVal = 0; int iopStart = sIndex; int rs; @@ -340,7 +385,10 @@ static int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, in * set ups state according to rules, do adjustments for CHRG/DISCHRG * and battery charge states */ -static void update_ups_states(struct gpioups_t *gpioupsfdlocal) { +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +static +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +void update_ups_states(struct gpioups_t *gpioupsfdlocal) { int batLow = 0; int bypass = 0; int chargerStatusSet = 0; diff --git a/drivers/generic_gpio_common.h b/drivers/generic_gpio_common.h index a0811756fb..65c60a9e34 100644 --- a/drivers/generic_gpio_common.h +++ b/drivers/generic_gpio_common.h @@ -71,4 +71,15 @@ void gpio_open(struct gpioups_t *gpioupsfd); void gpio_get_lines_states(struct gpioups_t *gpioupsfd); void gpio_close(struct gpioups_t *gpioupsfd); +# ifdef DRIVERS_MAIN_WITHOUT_MAIN +/* Methods externalized for unit-tests, otherwise private to this module */ +struct gpioups_t *generic_gpio_open(const char *chipName); +void generic_gpio_close(struct gpioups_t *gpioupsfd); +void get_ups_rules(struct gpioups_t *upsfd, unsigned char *rulesString); +void add_rule_item(struct gpioups_t *upsfd, int newValue); +int get_rule_lex(unsigned char *rulesBuff, int *startPos, int *endPos); +int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sIndex); +void update_ups_states(struct gpioups_t *gpioupsfd); +# endif /* DRIVERS_MAIN_WITHOUT_MAIN */ + #endif /* GENERIC_GPIO_COMMON_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 6339f33c86..20ee867ff4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -62,7 +62,8 @@ if WITH_GPIO TESTS += gpiotest endif -gpiotest_SOURCES = generic_gpio_utest.c +gpiotest_SOURCES = generic_gpio_utest.c generic_gpio_liblocal.c +nodist_gpiotest_SOURCES = $(top_srcdir)/drivers/generic_gpio_libgpiod.c $(top_srcdir)/drivers/generic_gpio_common.c gpiotest_LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/drivers/libdummy_mockdrv.la gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h generic_gpio_test.txt diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 3b159c196e..14fa3cb6d0 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -22,19 +22,14 @@ #include "config.h" #include "main.h" +#include "dstate.h" #include "attribute.h" #include "generic_gpio_utest.h" -#include "generic_gpio_common.c" -#include - -#include "generic_gpio_liblocal.c" -#include "generic_gpio_libgpiod.c" +#include #include #include -#include "dstate.h" - extern struct gpioups_t *gpioupsfd; static int done=0; From 0345dbb4acbf54c4d4d86ce97ff8f745ad21de5a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 16:31:54 +0100 Subject: [PATCH 0568/1232] NEWS: libdummy_mockdrv.la added [#1855] --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 94293e47d4..a80f6213d7 100644 --- a/NEWS +++ b/NEWS @@ -263,6 +263,11 @@ https://github.com/networkupstools/nut/milestone/8 `nut-server.service` as `upsd.service`, and `nut-monitor.service` as `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Recipes and `main.c` code were enhanced to produce a `libdummy_mockdrv.la` + helper library during build (not intended to be installed nor distributed), + in order to facilitate creation of test programs which behave like a driver + [#1855] + - Further revision of public headers delivered by NUT was done, particularly to address lack of common data types (`size_t`, `ssize_t`, `uint16_t`, `time_t` etc.) in third-party client code that earlier sufficed to only From 36f37f77d11ca4842efbbade46a3988c882daed0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 16:32:30 +0100 Subject: [PATCH 0569/1232] tests/Makefile.am: simplify recipe for gpiotest --- tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 20ee867ff4..5d08e2b459 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,9 +64,9 @@ endif gpiotest_SOURCES = generic_gpio_utest.c generic_gpio_liblocal.c nodist_gpiotest_SOURCES = $(top_srcdir)/drivers/generic_gpio_libgpiod.c $(top_srcdir)/drivers/generic_gpio_common.c -gpiotest_LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/drivers/libdummy_mockdrv.la +gpiotest_LDADD = $(top_builddir)/drivers/libdummy_mockdrv.la gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 -EXTRA_DIST += generic_gpio_liblocal.c generic_gpio_utest.h generic_gpio_test.txt +EXTRA_DIST += generic_gpio_utest.h generic_gpio_test.txt # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/drivers/libdummy_mockdrv.la \ From d9bcd8333c5343f3963a312b1fc60820272302f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 14 Mar 2023 09:01:05 +0100 Subject: [PATCH 0570/1232] fixup! NEWS: libdummy_mockdrv.la added [#1855] --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 51c7f7864d..79cda40584 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3106 utf-8 +personal_ws-1.1 en 3108 utf-8 AAS ABI ACFAIL @@ -2136,6 +2136,7 @@ libcppunit libcrypto libcurl libdir +libdummy libexec libfreeipmi libgd @@ -2293,6 +2294,7 @@ mmZ mmap mmddyyyy mn +mockdrv modbus modelname modprobe From 7fe1fb3fa2f2e7070495188e909ee47e6a524f9c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 00:42:05 +0100 Subject: [PATCH 0571/1232] tests/Makefile.am: relocate "endif" lines back, with a different way for sources of tests are always redistributed --- tests/Makefile.am | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5d08e2b459..45624ca886 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,22 +50,27 @@ hidparser.c: $(top_srcdir)/drivers/hidparser.c if WITH_USB TESTS += getvaluetest -endif getvaluetest_SOURCES = getvaluetest.c nodist_getvaluetest_SOURCES = hidparser.c # Pull the right include path for chosen libusb version: getvaluetest_CFLAGS = $(AM_CFLAGS) $(LIBUSB_CFLAGS) getvaluetest_LDADD = $(top_builddir)/common/libcommon.la +else +EXTRA_DIST += getvaluetest.c hidparser.c +endif if WITH_GPIO TESTS += gpiotest -endif gpiotest_SOURCES = generic_gpio_utest.c generic_gpio_liblocal.c nodist_gpiotest_SOURCES = $(top_srcdir)/drivers/generic_gpio_libgpiod.c $(top_srcdir)/drivers/generic_gpio_common.c gpiotest_LDADD = $(top_builddir)/drivers/libdummy_mockdrv.la gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 +else +EXTRA_DIST += generic_gpio_utest.c generic_gpio_liblocal.c +endif + EXTRA_DIST += generic_gpio_utest.h generic_gpio_test.txt # Make sure out-of-dir dependencies exist (especially when dev-building parts): From f1ac7434e61c9449f706fc3d13081e789d133694 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 01:07:33 +0100 Subject: [PATCH 0572/1232] tests/Makefile.am, tests/.gitignore: refer to generic_gpio_libgpiod.c/generic_gpio_common.c differently for portability --- tests/.gitignore | 2 ++ tests/Makefile.am | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/.gitignore b/tests/.gitignore index fe7beea504..a8aa04a5c3 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -17,3 +17,5 @@ /getvaluetest.log /getvaluetest.trs /hidparser.c +/generic_gpio_libgpiod.c +/generic_gpio_common.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 45624ca886..60ac604bfb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,8 +63,16 @@ endif if WITH_GPIO TESTS += gpiotest +# NOTE: Not using "$<" due to a legacy Sun/illumos dmake bug with resolver +# of dynamic vars, see e.g. https://man.omnios.org/man1/make#BUGS +generic_gpio_libgpiod.c: $(top_srcdir)/drivers/generic_gpio_libgpiod.c + test -s "$@" || ln -s -f "$(top_srcdir)/drivers/generic_gpio_libgpiod.c" "$@" + +generic_gpio_common.c: $(top_srcdir)/drivers/generic_gpio_common.c + test -s "$@" || ln -s -f "$(top_srcdir)/drivers/generic_gpio_common.c" "$@" + gpiotest_SOURCES = generic_gpio_utest.c generic_gpio_liblocal.c -nodist_gpiotest_SOURCES = $(top_srcdir)/drivers/generic_gpio_libgpiod.c $(top_srcdir)/drivers/generic_gpio_common.c +nodist_gpiotest_SOURCES = generic_gpio_libgpiod.c generic_gpio_common.c gpiotest_LDADD = $(top_builddir)/drivers/libdummy_mockdrv.la gpiotest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 else From 19feefefcfb714e7d7f56d59ed36acd9edba0054 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 13 Mar 2023 04:05:35 +0100 Subject: [PATCH 0573/1232] tests/Makefile.am: clean away symlinked gpiotest sources --- tests/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile.am b/tests/Makefile.am index 60ac604bfb..3a3b16871d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -79,6 +79,7 @@ else EXTRA_DIST += generic_gpio_utest.c generic_gpio_liblocal.c endif +CLEANFILES += generic_gpio_libgpiod.c generic_gpio_common.c EXTRA_DIST += generic_gpio_utest.h generic_gpio_test.txt # Make sure out-of-dir dependencies exist (especially when dev-building parts): From ed668987d2f24366afe28fe7900ae51a44984710 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 11:23:26 +0100 Subject: [PATCH 0574/1232] tests/NIT/nit.sh: double-quote the driverpath value so it is properly parsed --- 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 424c2cfba3..0470e6c6d8 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -466,7 +466,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\"" >> "$NUT_CONFPATH/ups.conf" || exit fi if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit From 23f2956a50a58ce6318adc9794d28062ec89cc26 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 11:49:00 +0100 Subject: [PATCH 0575/1232] drivers/upsdrvctl.c: complete the fix for upsdrvctl explicit fore-/back-grounding mode [#1806 follow-up] --- drivers/upsdrvctl.c | 113 ++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 8eaf8268b8..c69fffe360 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -270,72 +270,83 @@ static void forkexec(char *const argv[], const ups_t *ups) { #ifndef WIN32 int ret; - pid_t pid; - pid = fork(); + if (nut_foreground_passthrough != 1) { + pid_t pid; - if (pid < 0) - fatal_with_errno(EXIT_FAILURE, "fork"); + pid = fork(); - if (pid != 0) { /* parent */ - int wstat; - struct sigaction sa; + if (pid < 0) + fatal_with_errno(EXIT_FAILURE, "fork"); - /* Handle "parallel" drivers startup */ - if (waitfordrivers == 0) { - upsdebugx(2, "'nowait' set, continuing..."); - return; - } + if (pid != 0) { /* parent */ + int wstat; + struct sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = waitpid_timeout; - sigaction(SIGALRM, &sa, NULL); - - /* Use the local maxstartdelay, if available */ - if (ups->maxstartdelay != -1) { - if (ups->maxstartdelay >= 0) - alarm((unsigned int)ups->maxstartdelay); - } else { /* Otherwise, use the global (or default) value */ - if (maxstartdelay >= 0) - alarm((unsigned int)maxstartdelay); - } + /* Handle "parallel" drivers startup */ + if (waitfordrivers == 0) { + upsdebugx(2, "'nowait' set, continuing..."); + return; + } - ret = waitpid(pid, &wstat, 0); + if (nut_foreground_passthrough != 0 + && nut_debug_level > 0 + && nut_debug_level_passthrough > 0 + ) { + upsdebugx(2, "Starting driver with debug but without explicit backgrounding: will not wait for it to fork and detach, continuing..."); + return; + } - alarm(0); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = waitpid_timeout; + sigaction(SIGALRM, &sa, NULL); + + /* Use the local maxstartdelay, if available */ + if (ups->maxstartdelay != -1) { + if (ups->maxstartdelay >= 0) + alarm((unsigned int)ups->maxstartdelay); + } else { /* Otherwise, use the global (or default) value */ + if (maxstartdelay >= 0) + alarm((unsigned int)maxstartdelay); + } - if (ret == -1) { - upslogx(LOG_WARNING, "Startup timer elapsed, continuing..."); - exec_error++; - return; - } + ret = waitpid(pid, &wstat, 0); - if (WIFEXITED(wstat) == 0) { - upslogx(LOG_WARNING, "Driver exited abnormally"); - exec_error++; - return; - } + alarm(0); - if (WEXITSTATUS(wstat) != 0) { - upslogx(LOG_WARNING, "Driver failed to start" - " (exit status=%d)", WEXITSTATUS(wstat)); - exec_error++; - return; - } + if (ret == -1) { + upslogx(LOG_WARNING, "Startup timer elapsed, continuing..."); + exec_error++; + return; + } - /* the rest only work when WIFEXITED is nonzero */ + if (WIFEXITED(wstat) == 0) { + upslogx(LOG_WARNING, "Driver exited abnormally"); + exec_error++; + return; + } - if (WIFSIGNALED(wstat)) { - upslog_with_errno(LOG_WARNING, "Driver died after signal %d", - WTERMSIG(wstat)); - exec_error++; - } + if (WEXITSTATUS(wstat) != 0) { + upslogx(LOG_WARNING, "Driver failed to start" + " (exit status=%d)", WEXITSTATUS(wstat)); + exec_error++; + return; + } - return; + /* the rest only work when WIFEXITED is nonzero */ + + if (WIFSIGNALED(wstat)) { + upslog_with_errno(LOG_WARNING, "Driver died after signal %d", + WTERMSIG(wstat)); + exec_error++; + } + + return; + } } - /* child */ + /* child or foreground mode (no fork) */ ret = execv(argv[0], argv); From 44f57e7b4931637c52a6668cd3b296d28afd8965 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 13:20:32 +0100 Subject: [PATCH 0576/1232] drivers/upsdrvctl.c: count the UPSes we would command; foregrounding behavior depends on that number --- drivers/upsdrvctl.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index c69fffe360..12dd068d43 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -46,6 +46,7 @@ typedef struct { } ups_t; static ups_t *upstable = NULL; +static int upscount = 0; static int maxsdorder = 0, testmode = 0, exec_error = 0; @@ -271,7 +272,9 @@ static void forkexec(char *const argv[], const ups_t *ups) #ifndef WIN32 int ret; - if (nut_foreground_passthrough != 1) { + if (nut_foreground_passthrough == 1 && upscount == 1) { + upsdebugx(1, "Starting the only driver with explicitly requested foregrounding mode, not forking"); + } else { pid_t pid; pid = fork(); @@ -289,6 +292,15 @@ static void forkexec(char *const argv[], const ups_t *ups) return; } + if (nut_foreground_passthrough == 1 && upscount > 1) { + /* Let upsdrvctl fork to run its numerous children + * but without further forking on their side - so + * not waiting for them to complete start-ups. + */ + upsdebugx(1, "Starting driver with explicitly requested foregrounding mode: will not wait for it to fork and detach, continuing.."); + return; + } + if (nut_foreground_passthrough != 0 && nut_debug_level > 0 && nut_debug_level_passthrough > 0 @@ -793,10 +805,24 @@ int main(int argc, char **argv) read_upsconf(); - if (argc == 1) + if (argc == 1) { + ups_t *tmp = upstable; + upscount = 0; + + while (tmp) { + tmp = tmp->next; + upscount++; + } + + upsdebugx(1, "upsdrvctl commanding all drivers (%d found): %s", + upscount, argv[0]); send_all_drivers(command); - else + } else { + upscount = 1; + upsdebugx(1, "upsdrvctl commanding one driver (%s): %s", + argv[1], argv[0]); send_one_driver(command, argv[1]); + } if (exec_error) exit(EXIT_FAILURE); From db86be83ece58d26a1d5d8c726dcd4bca4a66764 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 13:20:51 +0100 Subject: [PATCH 0577/1232] drivers/upsdrvctl.c: log when the tool is exiting --- drivers/upsdrvctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 12dd068d43..f608979c25 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -692,6 +692,8 @@ static void exit_cleanup(void) { ups_t *tmp, *next; + upsdebugx(1, "Completed the job of upsdrvctl tool, cleaning up and exiting now"); + tmp = upstable; while (tmp) { From cbd1141dac66f1ec979e035685068409d2db16a3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 13:21:10 +0100 Subject: [PATCH 0578/1232] drivers/upsdrvctl.c: do not exit the tool if foregrounding was requested --- drivers/upsdrvctl.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index f608979c25..7b2167217f 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -829,5 +829,22 @@ int main(int argc, char **argv) if (exec_error) exit(EXIT_FAILURE); + if (command == &start_driver + && upscount > 0 + && nut_foreground_passthrough == 1 + ) { + /* Note: for a single started driver, we just + * exec() it and should not even get here + */ + upsdebugx(1, "upsdrvctl was asked for explicit foregrounding - not exiting now (driver startup was completed)"); + while (1) { + /* FIXME: Add signal handler to exit(0) when getting + * a Ctrl+C, SIGTERM etc., and to command the launched + * driver(s) to stop. + */ + sleep(1); + } + } + exit(EXIT_SUCCESS); } From 559994c56cde4dffae681c5edbce9d8c3a57ce51 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 13:26:22 +0100 Subject: [PATCH 0579/1232] drivers/upsdrvctl.c: update logged messages about foregrounding mode --- drivers/upsdrvctl.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 7b2167217f..ab015f2c43 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -508,7 +508,8 @@ static void start_driver(const ups_t *ups) ) { upsdebugx(1, "WARNING: Requested a debugging level " "but not explicitly a backgrounding mode - " - "driver may never try to fork away"); + "driver may never try to fork away; however " + "the upsdrvctl tool will fork it and not wait."); } } @@ -661,9 +662,15 @@ static void send_all_drivers(void (*command)(const ups_t *)) ) ) { upslogx(LOG_WARNING, - "Starting \"all\" drivers but requested the " - "foreground mode (or debug without backgrounding)! " - "This request may never loop past the first driver!"); + "Starting \"all\" drivers but requested the %s!" + "This request will not wait for driver(s) to complete " + "their initialization%s.", + (nut_foreground_passthrough == 1 + ? "foreground mode" + : "debug mode without backgrounding"), + (nut_foreground_passthrough == 1 + ? ", but upsdrvctl tool will stay foregrounded" : "") + ); } while (ups) { From 21e5be498c84a32bd4da64cfb63a7bacae41ecbb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 14:03:33 +0100 Subject: [PATCH 0580/1232] docs/man/upsdrvctl.txt, NEWS: update info about upsdrvctl foregrounding mode support --- NEWS | 6 ++++-- docs/man/upsdrvctl.txt | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index f5b85d8bbd..e86e340ed5 100644 --- a/NEWS +++ b/NEWS @@ -64,8 +64,10 @@ https://github.com/networkupstools/nut/milestone/8 complicate (or simplify, when intentional) the management of service instances. Now there are explicit `upsdrvctl` options for choosing this (`-F`/`-B`), although default behavior is retained. Note that - foregrounding and mass-management loop to start all drivers (without - specifying the single device) do not play well together [#1759] + explicit foregrounding mode also keeps `upsdrvctl` tool from exiting + and would not wait for one driver to complete initialization before + starting another in case of mass-management loop to start all drivers + (without specifying the single device) [#1759, #1806, #1875] - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index c2c86cdcf6..2bc77e5a5d 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -57,6 +57,8 @@ This may be set in ups.conf with "user" in the global section. *-D*:: Raise the debug level. Use this multiple times for additional details. +Note that this does not preclude the `upsdrvctl` tool from exiting after +its job is done (however an explicit *-F* option does). *-d*:: Pass the selected debug level from `upsdrvctl` to launched drivers. @@ -65,9 +67,10 @@ in foreground mode; you can specify *-B* additionally to avoid that. *-F*:: Driver will run in the foreground (not fork away from the `upsdrvctl` -process), regardless of debugging settings. This may be counterproductive -if you start "everything" (do not specify an *ups* argument) as the loop -would never proceed beyond the first device in the list, so `upsdrvctl` +process), regardless of debugging settings. It would also keep the tool +program itself foregrounded with driver daemons running as its children +(in case of a single driver startup, it would not even fork). It would +also not wait for drivers to complete initialization, so `upsdrvctl` will warn about such situations. *-B*:: From b4cd7263a610cdf352cfde1ba04469e50487b090 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 14:13:45 +0100 Subject: [PATCH 0581/1232] drivers/upsdrvctl.c: fix logged message markup and TODO comments for foregrounded mode --- drivers/upsdrvctl.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index ab015f2c43..7b57f005f1 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -273,7 +273,8 @@ static void forkexec(char *const argv[], const ups_t *ups) int ret; if (nut_foreground_passthrough == 1 && upscount == 1) { - upsdebugx(1, "Starting the only driver with explicitly requested foregrounding mode, not forking"); + upsdebugx(1, "Starting the only driver with explicitly " + "requested foregrounding mode, not forking"); } else { pid_t pid; @@ -297,7 +298,9 @@ static void forkexec(char *const argv[], const ups_t *ups) * but without further forking on their side - so * not waiting for them to complete start-ups. */ - upsdebugx(1, "Starting driver with explicitly requested foregrounding mode: will not wait for it to fork and detach, continuing.."); + upsdebugx(1, "Starting driver with explicitly " + "requested foregrounding mode: will not " + "wait for it to fork and detach, continuing..."); return; } @@ -305,7 +308,10 @@ static void forkexec(char *const argv[], const ups_t *ups) && nut_debug_level > 0 && nut_debug_level_passthrough > 0 ) { - upsdebugx(2, "Starting driver with debug but without explicit backgrounding: will not wait for it to fork and detach, continuing..."); + upsdebugx(2, "Starting driver with debug but " + "without explicit backgrounding: " + "will not wait for it to fork and " + "detach, continuing..."); return; } @@ -843,11 +849,14 @@ int main(int argc, char **argv) /* Note: for a single started driver, we just * exec() it and should not even get here */ - upsdebugx(1, "upsdrvctl was asked for explicit foregrounding - not exiting now (driver startup was completed)"); + upsdebugx(1, "upsdrvctl was asked for explicit foregrounding - " + "not exiting now (driver startup was completed)"); while (1) { /* FIXME: Add signal handler to exit(0) when getting * a Ctrl+C, SIGTERM etc., and to command the launched - * driver(s) to stop. + * driver(s) to stop (need to remember the PIDs). Also + * track if any child has stopped (error, exit, signal...) + * to kill others and exit - with error if applicable. */ sleep(1); } From e36f8c91c96399bbec50f403c56c25704bad42b1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 14:59:21 +0100 Subject: [PATCH 0582/1232] drivers/upsdrvctl.c: track started foregrounded driver PID(s) to stop when exiting on signal --- drivers/upsdrvctl.c | 181 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 153 insertions(+), 28 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 7b57f005f1..7690992ca9 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -42,6 +42,11 @@ typedef struct { char *port; int sdorder; int maxstartdelay; +#ifndef WIN32 + pid_t pid; +#else + int pid; /* for WIN32 used just as a flag that this UPS was started by this tool in this run */ +#endif void *next; } ups_t; @@ -72,6 +77,12 @@ static char *pt_root = NULL, *pt_user = NULL; static int nut_debug_level_passthrough = 0; static int nut_foreground_passthrough = -1; +/* Keep track of requested operation (function pointer) */ +static void (*command)(const ups_t *) = NULL; + +/* signal handling */ +static int exit_flag = 0; + void do_upsconf_args(char *upsname, char *var, char *val) { ups_t *tmp, *last; @@ -138,6 +149,7 @@ void do_upsconf_args(char *upsname, char *var, char *val) tmp->upsname = xstrdup(upsname); tmp->driver = NULL; tmp->port = NULL; + tmp->pid = -1; tmp->next = NULL; tmp->sdorder = 0; tmp->maxstartdelay = -1; /* use global value by default */ @@ -163,26 +175,34 @@ static void stop_driver(const ups_t *ups) upsdebugx(1, "Stopping UPS: %s", ups->upsname); #ifndef WIN32 - struct stat fs; - snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(), - ups->driver, ups->upsname); - ret = stat(pidfn, &fs); - - if ((ret != 0) && (ups->port != NULL)) { - upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); + if (ups->pid == -1) { + struct stat fs; snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(), - ups->driver, xbasename(ups->port)); + ups->driver, ups->upsname); ret = stat(pidfn, &fs); - } - if (ret != 0) { - upslog_with_errno(LOG_ERR, "Can't open %s either", pidfn); - exec_error++; - return; - } + if ((ret != 0) && (ups->port != NULL)) { + upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); + snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(), + ups->driver, xbasename(ups->port)); + ret = stat(pidfn, &fs); + } + if (ret != 0) { + upslog_with_errno(LOG_ERR, "Can't open %s either", pidfn); + exec_error++; + return; + } + } else { + /* We started the driver in this run of upsdrvctl + * tool, stayed foregrounded, and now are exiting. + * NOTE: Not a filename here, but using same variable + * name makes the code below simpler to maintain. + */ + snprintf(pidfn, sizeof(pidfn), "PID %" PRIdMAX, (intmax_t)ups->pid); + } #else - snprintf(pidfn, sizeof(pidfn), "%s-%s",ups->driver, ups->upsname); + snprintf(pidfn, sizeof(pidfn), "%s-%s", ups->driver, ups->upsname); #endif upsdebugx(2, "Sending signal to %s", pidfn); @@ -191,7 +211,15 @@ static void stop_driver(const ups_t *ups) return; #ifndef WIN32 - ret = sendsignalfn(pidfn, SIGTERM); + if (ups->pid == -1) { + ret = sendsignalfn(pidfn, SIGTERM); + } else { + ret = sendsignalpid(ups->pid, SIGTERM); + /* reap zombie if this child died */ + if (waitpid(ups->pid, NULL, WNOHANG) == ups->pid) { + return; + } + } #else ret = sendsignal(pidfn, COMMAND_STOP); #endif @@ -199,7 +227,15 @@ static void stop_driver(const ups_t *ups) if (ret < 0) { #ifndef WIN32 upsdebugx(2, "SIGTERM to %s failed, retrying with SIGKILL", pidfn); - ret = sendsignalfn(pidfn, SIGKILL); + if (ups->pid == -1) { + ret = sendsignalfn(pidfn, SIGKILL); + } else { + ret = sendsignalpid(ups->pid, SIGKILL); + /* reap zombie if this child died */ + if (waitpid(ups->pid, NULL, WNOHANG) == ups->pid) { + return; + } + } #else upsdebugx(2, "Stopping %s failed, retrying again", pidfn); ret = sendsignal(pidfn, COMMAND_STOP); @@ -212,7 +248,20 @@ static void stop_driver(const ups_t *ups) } for (i = 0; i < 5 ; i++) { - if (sendsignalfn(pidfn, 0) != 0) { +#ifndef WIN32 + if (ups->pid == -1) { + ret = sendsignalfn(pidfn, 0); + } else { + /* reap zombie if this child died */ + if (waitpid(ups->pid, NULL, WNOHANG) == ups->pid) { + return; + } + ret = sendsignalpid(ups->pid, 0); + } +#else + ret = sendsignalfn(pidfn, 0); +#endif + if (ret != 0) { upsdebugx(2, "Sending signal to %s failed, driver is finally down or wrongly owned", pidfn); return; } @@ -221,18 +270,41 @@ static void stop_driver(const ups_t *ups) #ifndef WIN32 upslog_with_errno(LOG_ERR, "Stopping %s failed, retrying harder", pidfn); - ret = sendsignalfn(pidfn, SIGKILL); + if (ups->pid == -1) { + ret = sendsignalfn(pidfn, SIGKILL); + } else { + /* reap zombie if this child died */ + if (waitpid(ups->pid, NULL, WNOHANG) == ups->pid) { + return; + } + ret = sendsignalpid(ups->pid, SIGKILL); + } #else upslog_with_errno(LOG_ERR, "Stopping %s failed, retrying again", pidfn); ret = sendsignal(pidfn, COMMAND_STOP); #endif if (ret == 0) { for (i = 0; i < 5 ; i++) { - if (sendsignalfn(pidfn, 0) != 0) { +#ifndef WIN32 + if (ups->pid == -1) { + ret = sendsignalfn(pidfn, 0); + } else { + /* reap zombie if this child died */ + if (waitpid(ups->pid, NULL, WNOHANG) == ups->pid) { + return; + } + ret = sendsignalpid(ups->pid, 0); + } +#else + ret = sendsignalfn(pidfn, 0); +#endif + if (ret != 0) { upsdebugx(2, "Sending signal to %s failed, driver is finally down or wrongly owned", pidfn); // While a TERMinated driver cleans up, // a stuck and KILLed one does not, so: - unlink(pidfn); + if (ups->pid == -1) { + unlink(pidfn); + } return; } sleep(1); @@ -243,6 +315,38 @@ static void stop_driver(const ups_t *ups) exec_error++; } +void set_exit_flag(const int sig) +{ + exit_flag = sig; +} + +static void setup_signals(void) +{ +#ifndef WIN32 + /* Keep in sync with signal handling in drivers/main.c */ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = set_exit_flag; + + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + sa.sa_handler = SIG_IGN; +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES) +# pragma GCC diagnostic pop +#endif + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); +#endif /* WIN32 */ +} + #ifndef WIN32 static void waitpid_timeout(const int sig) { @@ -287,6 +391,10 @@ static void forkexec(char *const argv[], const ups_t *ups) int wstat; struct sigaction sa; + /* work around const for this one... */ + int *pupid = (int *)&(ups->pid); + *pupid = pid; + /* Handle "parallel" drivers startup */ if (waitfordrivers == 0) { upsdebugx(2, "'nowait' set, continuing..."); @@ -417,6 +525,10 @@ static void forkexec(char *const argv[], const ups_t *ups) upslogx(LOG_WARNING, "Driver failed to start (exit status=%d)", ret); exec_error++; return; + } else { + /* work around const for this one... */ + int *pupid = (int *)&(ups->pid); + *pupid = 0; /* Here, just a flag (not "-1" has a meaning) */ } return; @@ -709,6 +821,21 @@ static void exit_cleanup(void) tmp = upstable; + if (command == &start_driver + && upscount > 0 + && nut_foreground_passthrough == 1 + ) { + /* First stop the drivers, if any are running */ + while (tmp) { + next = tmp->next; + if (tmp->pid != -1) { + stop_driver(tmp); + } + tmp = next; + } + } + + tmp = upstable; while (tmp) { next = tmp->next; @@ -727,7 +854,6 @@ int main(int argc, char **argv) { int i; char *prog; - void (*command)(const ups_t *) = NULL; printf("Network UPS Tools - UPS driver controller %s\n", UPS_VERSION); @@ -851,12 +977,11 @@ int main(int argc, char **argv) */ upsdebugx(1, "upsdrvctl was asked for explicit foregrounding - " "not exiting now (driver startup was completed)"); - while (1) { - /* FIXME: Add signal handler to exit(0) when getting - * a Ctrl+C, SIGTERM etc., and to command the launched - * driver(s) to stop (need to remember the PIDs). Also - * track if any child has stopped (error, exit, signal...) - * to kill others and exit - with error if applicable. + setup_signals(); + while (!exit_flag) { + /* FIXME: track if any child has stopped (due to + * an error, normal exit, signal...) to kill others + * and exit the tool - with error if applicable. */ sleep(1); } From d065309b1a5386155868e3d29ae183b17cc8dadb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 14:59:37 +0100 Subject: [PATCH 0583/1232] drivers/upsdrvctl.c: fix some WIN32 code style --- drivers/upsdrvctl.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 7690992ca9..1b93544073 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -480,22 +480,22 @@ static void forkexec(char *const argv[], const ups_t *ups) fatal_with_errno(EXIT_FAILURE, "execv"); #else BOOL ret; - DWORD res; - DWORD exit_code = 0; + DWORD res; + DWORD exit_code = 0; char commandline[SMALLBUF]; - STARTUPINFO StartupInfo; - PROCESS_INFORMATION ProcessInformation; - int i = 1; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + int i = 1; memset(&StartupInfo,0,sizeof(STARTUPINFO)); /* the command line is made of the driver name followed by args */ snprintf(commandline,sizeof(commandline),"%s", ups->driver); - while( argv[i] != NULL ) { + while (argv[i] != NULL) { snprintfcat(commandline, sizeof(commandline), " %s", argv[i]); i++; } - + ret = CreateProcess( argv[0], commandline, @@ -509,17 +509,17 @@ static void forkexec(char *const argv[], const ups_t *ups) &ProcessInformation ); - if( ret == 0 ) { + if (ret == 0) { fatal_with_errno(EXIT_FAILURE, "execv"); } - + /* Wait a bit then look at driver process. Unlike under Linux, Windows spwan drivers directly. If the driver is alive, all is OK. An optimization can probably be implemented to prevent waiting so much time when all is OK. */ res = WaitForSingleObject(ProcessInformation.hProcess, (ups->maxstartdelay!=-1?ups->maxstartdelay:maxstartdelay)*1000); - + if (res != WAIT_TIMEOUT) { GetExitCodeProcess( ProcessInformation.hProcess, &exit_code ); upslogx(LOG_WARNING, "Driver failed to start (exit status=%d)", ret); @@ -530,7 +530,7 @@ static void forkexec(char *const argv[], const ups_t *ups) int *pupid = (int *)&(ups->pid); *pupid = 0; /* Here, just a flag (not "-1" has a meaning) */ } - + return; #endif } From b0fdcea4ffe5859bbc9ec541a28ad8ff4b3b3fda Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 17:02:57 +0100 Subject: [PATCH 0584/1232] drivers/upsdrvctl.c: track if any of launched foreground-mode drivers exited, and then abort the whole bundle (so it can be consistently restarted) --- drivers/upsdrvctl.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 1b93544073..8b497f6684 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -977,12 +977,34 @@ int main(int argc, char **argv) */ upsdebugx(1, "upsdrvctl was asked for explicit foregrounding - " "not exiting now (driver startup was completed)"); + + /* raise exit_flag upon SIGTERM, Ctrl+C, etc. */ setup_signals(); while (!exit_flag) { - /* FIXME: track if any child has stopped (due to + /* Track if any child process has stopped (due to * an error, normal exit, signal...) to kill others * and exit the tool - with error if applicable. */ + ups_t *tmp = upstable, *next; + while (tmp) { + next = tmp->next; + if (tmp->pid != -1) { + if (waitpid(tmp->pid, NULL, WNOHANG) == tmp->pid) { + exit_flag = -1; + tmp->pid = -1; + } + } + tmp = next; + } + if (exit_flag == -1) { + fatalx(EXIT_FAILURE, "At least one tracked driver running " + "in foreground mode has exited, stopping upsdrvctl " + "(and other tracked drivers) so the bundle can be " + "restarted by system properly"); + /* NOTE: Users really should run one driver per instance, + * wrapped in services where available */ + } + sleep(1); } } From 3769dbaa5adde02aa11c5c345144c7e15e4648cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 19:54:49 +0100 Subject: [PATCH 0585/1232] drivers/upsdrvctl.c: only check for child process PIDs on POSIX platforms --- drivers/upsdrvctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 8b497f6684..2264edc2ec 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -981,6 +981,7 @@ int main(int argc, char **argv) /* raise exit_flag upon SIGTERM, Ctrl+C, etc. */ setup_signals(); while (!exit_flag) { +#ifndef WIN32 /* Track if any child process has stopped (due to * an error, normal exit, signal...) to kill others * and exit the tool - with error if applicable. @@ -996,6 +997,7 @@ int main(int argc, char **argv) } tmp = next; } + if (exit_flag == -1) { fatalx(EXIT_FAILURE, "At least one tracked driver running " "in foreground mode has exited, stopping upsdrvctl " @@ -1004,7 +1006,7 @@ int main(int argc, char **argv) /* NOTE: Users really should run one driver per instance, * wrapped in services where available */ } - +#endif /* WIN32 */ sleep(1); } } From 765a17faeae8d7c7bbea5b382dcc5988de08a892 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 21 Mar 2023 20:04:28 +0100 Subject: [PATCH 0586/1232] drivers/upsdrvctl.c: fix build warnings --- drivers/upsdrvctl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 2264edc2ec..7c5839240e 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -315,7 +315,7 @@ static void stop_driver(const ups_t *ups) exec_error++; } -void set_exit_flag(const int sig) +static void set_exit_flag(const int sig) { exit_flag = sig; } @@ -739,7 +739,7 @@ static void shutdown_driver(const ups_t *ups) } } -static void send_one_driver(void (*command)(const ups_t *), const char *upsname) +static void send_one_driver(void (*command_func)(const ups_t *), const char *upsname) { ups_t *ups = upstable; @@ -748,7 +748,7 @@ static void send_one_driver(void (*command)(const ups_t *), const char *upsname) while (ups) { if (!strcmp(ups->upsname, upsname)) { - command(ups); + command_func(ups); return; } @@ -759,7 +759,7 @@ static void send_one_driver(void (*command)(const ups_t *), const char *upsname) } /* walk UPS table and send command to all UPSes according to sdorder */ -static void send_all_drivers(void (*command)(const ups_t *)) +static void send_all_drivers(void (*command_func)(const ups_t *)) { ups_t *ups; int i; @@ -767,11 +767,11 @@ static void send_all_drivers(void (*command)(const ups_t *)) if (!upstable) fatalx(EXIT_FAILURE, "Error: no UPS definitions found in ups.conf"); - if (command != &shutdown_driver) { + if (command_func != &shutdown_driver) { ups = upstable; /* Only warn when relevant - got more than one device to start */ - if (command == &start_driver + if (command_func == &start_driver && ups->next && ( (nut_foreground_passthrough == 1) || (nut_foreground_passthrough != 0 @@ -792,7 +792,7 @@ static void send_all_drivers(void (*command)(const ups_t *)) } while (ups) { - command(ups); + command_func(ups); ups = ups->next; } @@ -806,7 +806,7 @@ static void send_all_drivers(void (*command)(const ups_t *)) while (ups) { if (ups->sdorder == i) - command(ups); + command_func(ups); ups = ups->next; } From d80478d5db05b4cd8014a927d14d9d78c935ef12 Mon Sep 17 00:00:00 2001 From: Evgeny Klimov Date: Wed, 22 Mar 2023 15:19:51 +0100 Subject: [PATCH 0587/1232] drivers/upsdrvctl.c: avoid another warning (WIN32 builds) --- drivers/upsdrvctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 7c5839240e..ec04cd14a4 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -322,6 +322,8 @@ static void set_exit_flag(const int sig) static void setup_signals(void) { + set_exit_flag(0); + #ifndef WIN32 /* Keep in sync with signal handling in drivers/main.c */ struct sigaction sa; From 79e7b251d349a3ae95b6959c7c18a909bc0a2bd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 23 Mar 2023 15:21:55 +0100 Subject: [PATCH 0588/1232] drivers/baytech-mib.c: update baytech_outlet_status_info[] valid values [#1871] --- NEWS | 2 ++ drivers/baytech-mib.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 0888669345..9718ae1666 100644 --- a/NEWS +++ b/NEWS @@ -137,6 +137,8 @@ https://github.com/networkupstools/nut/milestone/8 * Fixed the long standing "Warning: excessive poll failures" issue, that was tied to non-existent OIDs, not well handled in some parts of the driver [#1716] + * `baytech-mib.c` subdriver: fixed `baytech_outlet_status_info[]` set + of valid outlet status values [#1871] - The `bestfortress` driver shutdown handling was fixed to use a non-trivial default timeout [#1820] diff --git a/drivers/baytech-mib.c b/drivers/baytech-mib.c index 43098cdb6e..1ef69998d8 100644 --- a/drivers/baytech-mib.c +++ b/drivers/baytech-mib.c @@ -24,7 +24,7 @@ #include "baytech-mib.h" /* NOTE: last badly versioned release was "4032" but should be "X.Y[Z]"! */ -#define BAYTECH_MIB_VERSION "0.4034" +#define BAYTECH_MIB_VERSION "0.4035" /* Baytech MIB */ #define BAYTECH_OID_MIB ".1.3.6.1.4.1.4779" @@ -34,7 +34,11 @@ static info_lkp_t baytech_outlet_status_info[] = { { -1, "error", NULL, NULL }, { 0, "off", NULL, NULL }, { 1, "on", NULL, NULL }, - { 2, "cycling", NULL, NULL }, /* transitional status */ + { 2, "cycling", NULL, NULL }, /* transitional status, "reboot" in MIB comments */ + { 3, "lockon", NULL, NULL }, + { 4, "lockoff", NULL, NULL }, + { 5, "unlock", NULL, NULL }, + { 6, "unknown", NULL, NULL }, { 0, NULL, NULL, NULL } }; From 8474ac2f00a94e7958b1c9cb6fdd823615b63529 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 10:27:45 +0000 Subject: [PATCH 0589/1232] docs/ci-farm-lxc-setup.txt: clarify use of expired keys for ancient Debian releases --- docs/ci-farm-lxc-setup.txt | 24 +++++++++++++++++++++++- docs/nut.dict | 4 +++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/ci-farm-lxc-setup.txt b/docs/ci-farm-lxc-setup.txt index 1adb59c99f..466783e395 100644 --- a/docs/ci-farm-lxc-setup.txt +++ b/docs/ci-farm-lxc-setup.txt @@ -116,7 +116,8 @@ further options for each "template" by invoking its help action, e.g.: -n jenkins-debian10-mips -t debian -- \ -r buster -a mips ------ -** ...or for EOLed distros, use the archive, e.g.: +** ...or for EOLed distros, use the Debian Archive server. +*** Install the container with Debian Archive as the mirror like this: + ------ :; MIRROR="http://archive.debian.org/debian-archive/debian/" \ @@ -124,6 +125,27 @@ further options for each "template" by invoking its help action, e.g.: -n jenkins-debian8-s390x -t debian -- \ -r jessie -a s390x ------ +*** Note you may have to add trust to their (now expired) GPG keys for + packaging to verify signatures made at the time the key was valid, + by un-symlinking (if appropriate) the debootstrap script such as + `/usr/share/debootstrap/scripts/jessie`, commenting away the + `keyring /usr/share/keyrings/debian-archive-keyring.gpg` line and + setting `keyring /usr/share/keyrings/debian-archive-removed-keys.gpg` + instead. You may further have to edit `/usr/share/debootstrap/functions` + and/or `/usr/share/lxc/templates/lxc-debian` to honor that setting (the + `releasekeyring` was hard-coded in version I had installed), e.g. in the + latter file ensure such logic as below, and re-run the installation: ++ +------ +... + # If debian-archive-keyring isn't installed, fetch GPG keys directly + releasekeyring="`grep -E '^keyring ' "/usr/share/debootstrap/scripts/$release" | sed -e 's,^keyring ,,' -e 's,[ #].*$,,'`" 2>/dev/null + if [ -z $releasekeyring ]; then + releasekeyring=/usr/share/keyrings/debian-archive-keyring.gpg + fi + if [ ! -f $releasekeyring ]; then +... +------ ** ...Alternatively, other distributions can be used (as supported by your LXC scripts, typically in `/usr/share/debootstrap/scripts`), e.g. Ubuntu: + diff --git a/docs/nut.dict b/docs/nut.dict index 980318c63a..b89cf5576a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3114 utf-8 +personal_ws-1.1 en 3116 utf-8 AAS ABI ACFAIL @@ -2113,6 +2113,7 @@ keyclick keygen keyout keyring +keyrings keyserver killall killpower @@ -2609,6 +2610,7 @@ refactoring referencenominal regex regtype +releasekeyring relicensing repo reposurgeon From ed6d98c18e965a9b978940096aea665ef0a2d8b1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 10:38:44 +0000 Subject: [PATCH 0590/1232] docs/ci-farm-lxc-setup.txt: split container installation and setup into visible sub-chapters --- docs/ci-farm-lxc-setup.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/ci-farm-lxc-setup.txt b/docs/ci-farm-lxc-setup.txt index 466783e395..dd32950a07 100644 --- a/docs/ci-farm-lxc-setup.txt +++ b/docs/ci-farm-lxc-setup.txt @@ -96,6 +96,9 @@ further options for each "template" by invoking its help action, e.g.: ------ ====== +Initial container installation (for various guest OSes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Install containers like this: + ------ @@ -281,6 +284,9 @@ package integrity (seems too tied into thinking that host OS is Arch)... It seems that pre-fetching the package databases with `pacman -Sy` on the host was also important. +Initial container-related setup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Add the "name,IP" line for this container to `/etc/lxc/dnsmasq-hosts.conf` on the host, e.g.: + From c467bae0833894ea12831759c23bf8dc7c491035 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 11:11:53 +0000 Subject: [PATCH 0591/1232] docs/config-prereqs.txt: typo and markup fixes --- docs/config-prereqs.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index a1911ba322..43d33802f9 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -108,7 +108,7 @@ versioned package by default of the current release (e.g. "libusb-0.1-4"), while names of both the library and development packages for libusb-1.0 must be determined with: ------ -:; apt-cache search 'libusb.*1\.0.* +:; apt-cache search 'libusb.*1\.0.*' ------ yielding e.g. "libusb-1.0-0-dev" (string name was seen with different actual package source versions on both Debian 8 "Jessie" and @@ -121,16 +121,19 @@ metadata about recently published package revisions: ------ :; apt-get update -# NOTE: Older Debian-like distributions may lack a "libtool-bin" :; apt-get install \ ccache time \ git python perl curl \ - make autoconf automake libltdl-dev libtool-bin libtool \ + make autoconf automake libltdl-dev libtool \ valgrind \ cppcheck \ pkg-config \ gcc g++ clang +# NOTE: Older Debian-like distributions may lack a "libtool-bin" +:; apt-get install \ + libtool-bin + # NOTE: For python, you may eventually have to specify a variant like this # (numbers depending on default or additional packages of your distro): # :; apt-get install python2 python2.7 python-is-python2 @@ -165,13 +168,17 @@ metadata about recently published package revisions: libusb-dev libusb-1.0-0-dev \ libi2c-dev \ libmodbus-dev \ - libgpiod-dev \ libsnmp-dev \ libpowerman0-dev \ libfreeipmi-dev libipmimonitoring-dev \ libavahi-common-dev libavahi-core-dev libavahi-client-dev # For libneon, see below +# NOTE: Older Debian-like distributions may lack a "libgpiod-dev" +# Others above are present as far back as Debian 7 at least +:; apt-get install \ + libgpiod-dev + :; apt-get install \ lua5.1-dev From 1f7638f88ee5f47edde25e717259ecefc7a1a387 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 11:31:27 +0000 Subject: [PATCH 0592/1232] autogen.sh: suggest what to do in case of m4 "ifdef" errors --- autogen.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autogen.sh b/autogen.sh index bf9316afb9..d4f8866fc1 100755 --- a/autogen.sh +++ b/autogen.sh @@ -132,6 +132,10 @@ FAILED: did not generate an executable configure script! # scripts, and need you to explicitly say which version you want, e.g. # export AUTOCONF_VERSION=2.65 AUTOMAKE_VERSION=1.13 # If you get issues with AC_DISABLE_STATIC make sure you have libtool. +# If it complains about "too few" or "excess" "arguments to builtin ifdef", +# check the configure.ac line it refers to and un-comment (or comment away) +# the third argument for AM_SILENT_RULES check, or comment away the whole +# "ifdef" block if your autotools still would not grok it. EOF exit 1 } >&2 From 803a57e87d0a478f463996f02af6145ff4b70253 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 14:29:39 +0000 Subject: [PATCH 0593/1232] clients/nutclient.h: declare NutException&Co destructors as "noexcept" to match some system headers std::except --- clients/nutclient.cpp | 12 ++++++------ clients/nutclient.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clients/nutclient.cpp b/clients/nutclient.cpp index 7d700e2291..63ec2ae903 100644 --- a/clients/nutclient.cpp +++ b/clients/nutclient.cpp @@ -194,12 +194,12 @@ std::string SystemException::err() * https://lgtm.com/rules/2165180572/ like: * NutException& operator=(NutException& rhs) = default; */ -NutException::~NutException() {} -SystemException::~SystemException() {} -IOException::~IOException() {} -UnknownHostException::~UnknownHostException() {} -NotConnectedException::~NotConnectedException() {} -TimeoutException::~TimeoutException() {} +NutException::~NutException() noexcept {} +SystemException::~SystemException() noexcept {} +IOException::~IOException() noexcept {} +UnknownHostException::~UnknownHostException() noexcept {} +NotConnectedException::~NotConnectedException() noexcept {} +TimeoutException::~TimeoutException() noexcept {} namespace internal diff --git a/clients/nutclient.h b/clients/nutclient.h index 0399aae4f4..8047e26ced 100644 --- a/clients/nutclient.h +++ b/clients/nutclient.h @@ -60,7 +60,7 @@ class NutException : public std::exception NutException(const std::string& msg):_msg(msg){} NutException(const NutException&) = default; NutException& operator=(NutException& rhs) = default; - virtual ~NutException() override; + virtual ~NutException() noexcept override; virtual const char * what() const noexcept override {return this->_msg.c_str();} virtual std::string str() const noexcept {return this->_msg;} private: @@ -76,7 +76,7 @@ class SystemException : public NutException SystemException(); SystemException(const SystemException&) = default; SystemException& operator=(SystemException& rhs) = default; - virtual ~SystemException() override; + virtual ~SystemException() noexcept override; private: static std::string err(); }; @@ -91,7 +91,7 @@ class IOException : public NutException IOException(const std::string& msg):NutException(msg){} IOException(const IOException&) = default; IOException& operator=(IOException& rhs) = default; - virtual ~IOException() override; + virtual ~IOException() noexcept override; }; /** @@ -103,7 +103,7 @@ class UnknownHostException : public IOException UnknownHostException():IOException("Unknown host"){} UnknownHostException(const UnknownHostException&) = default; UnknownHostException& operator=(UnknownHostException& rhs) = default; - virtual ~UnknownHostException() override; + virtual ~UnknownHostException() noexcept override; }; /** @@ -115,7 +115,7 @@ class NotConnectedException : public IOException NotConnectedException():IOException("Not connected"){} NotConnectedException(const NotConnectedException&) = default; NotConnectedException& operator=(NotConnectedException& rhs) = default; - virtual ~NotConnectedException() override; + virtual ~NotConnectedException() noexcept override; }; /** @@ -127,7 +127,7 @@ class TimeoutException : public IOException TimeoutException():IOException("Timeout"){} TimeoutException(const TimeoutException&) = default; TimeoutException& operator=(TimeoutException& rhs) = default; - virtual ~TimeoutException() override; + virtual ~TimeoutException() noexcept override; }; /** From 03dfcb4505eadb8cad8725c0b78fd494e39d9e48 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 14:31:23 +0000 Subject: [PATCH 0594/1232] configure.ac: typo fix for "have_cxx11=no," verdict --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 81251ec2d8..ecd09de9a1 100644 --- a/configure.ac +++ b/configure.ac @@ -3267,7 +3267,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]]) [AS_CASE(["${CXXFLAGS}"], [*"-std="*], [ AC_MSG_RESULT([no, not with the standard already set in CXXFLAGS='${CXXFLAGS}']) - have_cxx11=no, + have_cxx11=no ],[ CXXFLAGS="$CXXFLAGS -std=c++11" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]])], From 91344b68877a97fc7c6bfb2489d0b38f196ea05d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 30 Mar 2023 14:35:35 +0000 Subject: [PATCH 0595/1232] configure.ac: test C++11 nuances that NUT uses and which fail with older gcc-4.x with intermediate levels of support --- configure.ac | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ecd09de9a1..af77acbb67 100644 --- a/configure.ac +++ b/configure.ac @@ -3258,8 +3258,17 @@ CPLUSPLUS_DECL=' #if __cplusplus < 201103L #error This library needs at least a C++11 compliant compiler #endif + +/* Make sure it supports modern syntax */ +#include +#include +' +CPLUSPLUS_MAIN=' +printf("%ld\n", __cplusplus); +/* Make sure it supports modern syntax */ +std::map map; +map.emplace("key", "value"); ' -CPLUSPLUS_MAIN='printf("%ld\n", __cplusplus);' AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]])], [AC_MSG_RESULT([yes, out of the box]) From f6726220477f1da56ea35796dc44788ac3ce7a6a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 11:44:25 +0200 Subject: [PATCH 0596/1232] autogen.sh: add "-v" or "export (CI_)DEBUG=true" support --- autogen.sh | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/autogen.sh b/autogen.sh index d4f8866fc1..b15a2e37cd 100755 --- a/autogen.sh +++ b/autogen.sh @@ -15,6 +15,14 @@ if [ -z "${LC_ALL-}" ] ; then export LC_ALL fi +VERBOSE_FLAG="" +if [ x"${DEBUG-}" = xtrue ] || [ x"${CI_DEBUG-}" = xtrue ] || [ x"$1" = x-v ] ; then + DEBUG=true + VERBOSE_FLAG="-v" + echo "NUT script $0 will call the tools with higher debug verbosity" +else + DEBUG=false +fi if [ -n "${PYTHON-}" ] ; then # May be a name/path of binary, or one with args - check both @@ -27,7 +35,9 @@ if [ -n "${PYTHON-}" ] ; then # Do not die just here, we may not need the interpreter } else + $DEBUG && echo "=== Picking usable Python version..." PYTHON="" + # FIXME: Use something like TAB-completion to find every name on PATH? for P in python python3 python2 \ python-3.10 python3.10 \ python-3.9 python3.9 \ @@ -36,11 +46,15 @@ else python-3.4 python3.4 \ python-2.7 python2.7 \ ; do - if (command -v "$P" >/dev/null) && $P -c "import re,glob,codecs" ; then + if (command -v "$P" >/dev/null) && $P $VERBOSE_FLAG -c "import re,glob,codecs" ; then + $DEBUG && echo "=== Picked usable Python version: $P" PYTHON="$P" break fi done + if $DEBUG && [ -z "$PYTHON" ] ; then + echo "=== Did not pick any usable Python version" + fi fi rm -f *.in.AUTOGEN_WITHOUT || true @@ -48,12 +62,12 @@ rm -f *.in.AUTOGEN_WITHOUT || true # re-generate files needed by configure, and created otherwise at 'dist' time if [ ! -f scripts/augeas/nutupsconf.aug.in ] then - if [ -n "${PYTHON-}" ] && $PYTHON -c "import re,glob,codecs"; then + if [ -n "${PYTHON-}" ] && $PYTHON $VERBOSE_FLAG -c "import re,glob,codecs"; then echo "Regenerating Augeas ups.conf lens with '$PYTHON'..." ( # That script is templated; assume @PYTHON@ is the only # road-bump there cd scripts/augeas \ - && $PYTHON ./gen-nutupsconf-aug.py.in + && $PYTHON $VERBOSE_FLAG ./gen-nutupsconf-aug.py.in ) || exit 1 else echo "----------------------------------------------------------------------" @@ -83,9 +97,17 @@ if [ ! -f scripts/udev/nut-usbups.rules.in -o \ ! -f tools/nut-scanner/nutscan-usb.h ] then if perl -e 1; then + VERBOSE_FLAG_PERL="" + if $DEBUG ; then + if perl -d:Devel::Trace -e 1 >/dev/null 2>/dev/null ; then + VERBOSE_FLAG_PERL="-d:Devel::Trace" + else + echo "=== Can not trace perl, try sudo cpan install 'Devel::Trace'" + fi + fi echo "Regenerating the USB helper files..." cd tools && { - ./nut-usbinfo.pl || exit 1 + perl $VERBOSE_FLAG_PERL ./nut-usbinfo.pl || exit 1 cd .. } else @@ -105,7 +127,9 @@ then fi if [ ! -f scripts/systemd/nut-common-tmpfiles.conf.in ]; then - echo '# autoconf requires this file exists before generating configure script; it will be overwritten by configure during a build' > scripts/systemd/nut-common-tmpfiles.conf.in + ( echo '# autoconf requires this file exists before generating configure script;' + echo '# it will be overwritten by running configure during an actual build' + ) > scripts/systemd/nut-common-tmpfiles.conf.in fi # now we can safely call autoreconf @@ -124,7 +148,17 @@ if ( command -v dos2unix ) 2>/dev/null >/dev/null ; then fi >&2 echo "Calling autoreconf..." -autoreconf -iv && [ -s configure ] && [ -x configure ] \ +AUTOTOOL_RES=0 +if $DEBUG ; then + autoreconf -iv --warnings=all -d || AUTOTOOL_RES=$? +else + # This tool's own verbosity is rather compact (whom it called) + # and not too useful for actual troubleshooting, while not too + # noisy to just disable. + autoreconf -iv || AUTOTOOL_RES=$? +fi + +[ "$AUTOTOOL_RES" = 0 ] && [ -s configure ] && [ -x configure ] \ || { cat << EOF FAILED: did not generate an executable configure script! @@ -166,7 +200,7 @@ fi # NOTE: Unquoted, may be multi-token $CONFIG_SHELL -n configure 2>/dev/null >/dev/null \ -|| { echo "FAILED: configure script did not pass shell interpreter syntax checks with $CONFIG_SHELL" >&2 ; +|| { echo "FAILED: configure script did not pass shell interpreter syntax checks with $CONFIG_SHELL" >&2 echo "NOTE: If you are using an older OS release, try executing the script with" >&2 echo "a more functional shell implementation (dtksh, bash, dash...)" >&2 echo "You can re-run this script with a CONFIG_SHELL in environment" >&2 From ae15a6083f9bced6be4606d83834a88fc7cb40e1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 11:48:27 +0200 Subject: [PATCH 0597/1232] configure.ac: use AM_PROG_AR if available (quiesce autoreconf portability warning) Inspired by https://github.com/vlm/asn1c/pull/63/files --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index af77acbb67..94e3579d95 100644 --- a/configure.ac +++ b/configure.ac @@ -2586,6 +2586,7 @@ then *-m64*) CC="$CC -m64" ;; esac fi +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) LT_INIT AC_SUBST([LIBTOOL_DEPS]) GCC="$SAVED_GCC" From 13291813582479337e0aadc352cafb9746b826aa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 11:53:20 +0200 Subject: [PATCH 0598/1232] configure.ac: use m4_ifdef for optional AM_SILENT_RULES support --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 94e3579d95..431b856300 100644 --- a/configure.ac +++ b/configure.ac @@ -86,8 +86,8 @@ dnl Default to `configure --enable-silent-rules` or `make V=1` for details? dnl This feature seems to require automake-1.13 or newer (1.11+ by other info) dnl On very old systems can comment it away with little loss (then automake-1.10 dnl is known to suffice): -ifdef(`AM_SILENT_RULES', `AM_SILENT_RULES([yes])') -dnl, `AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])' ) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], + [AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])]) dnl we need Autoconf 2.61 or better to enable features of Posix that are extensions to C dnl (and actually 2.64 or better for m4/ax_check_compile_flag.m4 when it is sourced) From 3d156a5d48ff315435a45f2659b1cf3dde26b647 Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 31 Mar 2023 13:12:30 +0200 Subject: [PATCH 0599/1232] Add usb_resetter instructions --- scripts/usb_resetter/README.md | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 scripts/usb_resetter/README.md diff --git a/scripts/usb_resetter/README.md b/scripts/usb_resetter/README.md new file mode 100644 index 0000000000..5b79650dd6 --- /dev/null +++ b/scripts/usb_resetter/README.md @@ -0,0 +1,47 @@ +Desc: Method for resetting unreliable USB UPS interfaces +File: scripts/usb_resetter/README +Date: 30 Mar 2023 +Auth: Orsiris de Jong - NetInvent SASU + +Some cheaper USB UPS have the same kind of unreliable USB to serial interface, being a Cypress Semiconductor USB to Serial / UNNO TECH USB to Serial. +Most of them use `blazer_usb` driver, and sometimes the driver can't start because it can't communicate with the UPS. + +Unplugging and plugging the USB port usually fixes this, but that's not convenient. + +That's where usb_resetter comes in handy. (see https://github.com/netinvent/usb_resetter for more info) +Grab a copy via pip with `pip install usb_resetter` or make a plain install with +``` +curl -o /usr/local/bin/usb_resetter -L https://raw.githubusercontent.com/netinvent/usb_resetter/main/usb_resetter/usb_resetter.py && chmod +x /usr/local/bin/usb_resetter +``` + +Once you got the script, identify the USB UPS with + +``` +usb_resetter --list +``` + +In our case, we could find something like `Found device 0665:5161 at /dev/bus/usb/001/002 Manufacturer=INNO TECH, Product=USB to Serial` + +usb_restter can work in three different ways: +- Reset device itself +- Reset the hub the device is attached to +- Reset all USB controllers + +A simple USB device reset isn't sufficient for those UPS devices. + +We'll need to reset the hub it's attached to. + +The command for doing so is: +``` +usb_reset.py --reset-hub --device 0665:5161 +``` + +Bear in mind that this will reset other devices connected to the same hub. While this isn't a problem for a keyboard / mouse, it might be for a USB storage device. +A good practice would be to isolate the USB UPS on a hub without any other device in order to not interfere with other hardware, or associate it on a hub where a non critical device is already plugged. + +The easiest way to integrate with nut-driver is to modify the systemd service file with the following line: +``` +ExecStartPre=/usr/local/bin/usb_reset.py --reset-hub --device 0665:5161 +``` + +This way, every time the nut-driver service is reloaded, the USB UPS is reset. From 31949f8c9c6b6b11ce65c3abe35ba753e42ef06e Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 31 Mar 2023 13:13:09 +0200 Subject: [PATCH 0600/1232] Add usb_resetter enabled nut-driver systemd service --- scripts/usb_resetter/nut-driver.service | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 scripts/usb_resetter/nut-driver.service diff --git a/scripts/usb_resetter/nut-driver.service b/scripts/usb_resetter/nut-driver.service new file mode 100644 index 0000000000..45018a0c67 --- /dev/null +++ b/scripts/usb_resetter/nut-driver.service @@ -0,0 +1,14 @@ +[Unit] +Description=Network UPS Tools - power device driver controller +After=local-fs.target network.target +StopWhenUnneeded=no + + +[Service] +ExecStartPre=-/usr/bin/systemd-tmpfiles --create /usr/lib/tmpfiles.d/nut-client.conf +ExecStartPre=/usr/local/bin/usb_resetter --reset-hub --device 0665:5161 +ExecStart=/usr/sbin/upsdrvctl start +ExecStop=/usr/sbin/upsdrvctl stop +Type=forking +Restart=on-failure +RestartSec=5s From f53d552a3a9ab769f4a0ebc0fcbb76fb6cede1c9 Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 31 Mar 2023 13:14:32 +0200 Subject: [PATCH 0601/1232] Add driver disconnected usb_resetter entry --- docs/FAQ.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/FAQ.txt b/docs/FAQ.txt index 2666478d97..805e175f9b 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -262,6 +262,8 @@ warnings; try a value like 25 or 30. == Why do the client programs say 'Driver not connected' when I try to run them? +*Answer 1* + This means that upsd can't connect to the driver for some reason. Your ups.conf entry might be wrong, or the driver might not be running. Maybe your state path is not configured properly. @@ -279,6 +281,15 @@ with 'upsdrvsvcctl resync' and then manage those with commands like 'upsdrvsvcctl stop' and 'upsdrvsvcctl start' (note that on other systems this tool may be not pre-installed via packaging). +*Answer 2* + +Some USB UPS devices have unreliable USB to serial interfaces. +In that case, it's advised to unplug / plug the device and try again. +If that resolves the issue, you should consider resetting the USB hub the device +is attached to before starting the nut driver, using usb_resetter script from +https://github.com/netinvent/usb_resetter +See scripts/usb_resetter for more information. + == Why don't the pathnames in your documentation match the package I installed? Each distribution has conventions for where specific file types should be From 1514d405166282d32b186df970ff2dbb3951f907 Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 31 Mar 2023 13:19:13 +0200 Subject: [PATCH 0602/1232] usb_resetter: add --list-hubs command example --- scripts/usb_resetter/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/usb_resetter/README.md b/scripts/usb_resetter/README.md index 5b79650dd6..27e20081fc 100644 --- a/scripts/usb_resetter/README.md +++ b/scripts/usb_resetter/README.md @@ -33,12 +33,19 @@ We'll need to reset the hub it's attached to. The command for doing so is: ``` -usb_reset.py --reset-hub --device 0665:5161 +usb_resetter --reset-hub --device 0665:5161 ``` Bear in mind that this will reset other devices connected to the same hub. While this isn't a problem for a keyboard / mouse, it might be for a USB storage device. +On some hardware, each USB plug gets it's own hub. On others, two or more USB plus share one hub. A good practice would be to isolate the USB UPS on a hub without any other device in order to not interfere with other hardware, or associate it on a hub where a non critical device is already plugged. +Getting the hub your device is attached to can be done with: +``` +usb_resetter --list-hubs --device 0665:5161 +``` + + The easiest way to integrate with nut-driver is to modify the systemd service file with the following line: ``` ExecStartPre=/usr/local/bin/usb_reset.py --reset-hub --device 0665:5161 From 37c24ffa1193524937e51ebff65d3d08cea978e2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 13:26:49 +0200 Subject: [PATCH 0603/1232] GitIgnore ar-lib tool, if added by automake (see AM_PROG_AR in configure.ac) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9862e66834..76342cad80 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ Makefile Makefile.in ## Parent directory only /aclocal.m4 +/ar-lib /autom4te.cache/ /ChangeLog /config.guess From 10b4b001364f9baaad844229660f837582262e37 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 14:07:45 +0200 Subject: [PATCH 0604/1232] configure.ac: detect support of dup() and/or dup2() on the platform --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index af77acbb67..326fbc7bca 100644 --- a/configure.ac +++ b/configure.ac @@ -595,7 +595,7 @@ AS_IF([test "$ac_cv_header_sys_time_h" = yes], and . This macro is deemed obsolete by autotools.]) ], []) -AC_CHECK_FUNCS(flock lockf fcvt fcvtl abs_val abs) +AC_CHECK_FUNCS(flock lockf fcvt fcvtl dup dup2 abs_val abs) AC_CHECK_HEADER([float.h], [AC_DEFINE([HAVE_FLOAT_H], [1], From dc234288dfd83e134789540458b9754edd0ad653 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 14:08:14 +0200 Subject: [PATCH 0605/1232] include/common.h: define STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO if absent on the platform --- include/common.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/common.h b/include/common.h index 7119ace6b6..c402f5677f 100644 --- a/include/common.h +++ b/include/common.h @@ -91,6 +91,19 @@ extern "C" { /* *INDENT-ON* */ #endif +/* POSIX requires these, and most but not all systems use same + * magical numbers for the file descriptors... yep, not all do! + */ +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 /* standard input file descriptor */ +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 /* standard output file descriptor */ +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 /* standard error file descriptor */ +#endif + /* porting stuff for WIN32, used by serial and SHUT codebases */ #ifndef WIN32 /* Just match three macro groups defined for WIN32 */ From 04a4c8e594047a9f9357a8ff9ccd7fedf7a7fb2c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 14:10:12 +0200 Subject: [PATCH 0606/1232] common/common.c: background(): use STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO macros instead of hard-coded FD 0-1-2 numbers [#1879, #1881] Closes: #1879 Closes: #1881 --- common/common.c | 64 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/common/common.c b/common/common.c index 5fbfed3073..d3b0937b94 100644 --- a/common/common.c +++ b/common/common.c @@ -203,24 +203,62 @@ void background(void) xbit_set(&upslog_flags, UPSLOG_SYSLOG); xbit_clear(&upslog_flags, UPSLOG_STDERR); - close(0); - close(1); - close(2); - - if (pid != 0) - _exit(EXIT_SUCCESS); /* parent */ + if (pid != 0) { + /* parent */ + /* these are typically fds 0-2: */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + _exit(EXIT_SUCCESS); + } /* child */ - /* make fds 0-2 point somewhere defined */ - if (open("/dev/null", O_RDWR) != 0) - fatal_with_errno(EXIT_FAILURE, "open /dev/null"); + /* make fds 0-2 (typically) point somewhere defined */ +#ifdef HAVE_DUP2 + /* system can close (if needed) and (re-)open a specific FD number */ + if (1) { /* scoping */ + TYPE_FD devnull = open("/dev/null", O_RDWR); + if (devnull < 0) + fatal_with_errno(EXIT_FAILURE, "open /dev/null"); + + if (dup2(devnull, STDIN_FILENO) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); + if (dup2(devnull, STDOUT_FILENO) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); + if (dup2(devnull, STDERR_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + + close(devnull); + } +#else +# ifdef HAVE_DUP + /* opportunistically duplicate to the "lowest-available" FD number */ + close(STDIN_FILENO); + if (open("/dev/null", O_RDWR) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); + + close(STDOUT_FILENO); + if (dup(STDIN_FILENO) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDOUT"); + + close(STDERR_FILENO); + if (dup(STDIN_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDERR"); +# else + close(STDIN_FILENO); + if (open("/dev/null", O_RDWR) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); + close(STDOUT_FILENO); + if (open("/dev/null", O_RDWR) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); + close(STDERR_FILENO); + if (open("/dev/null", O_RDWR) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); +# endif +#endif #ifdef HAVE_SETSID setsid(); /* make a new session to dodge signals */ From f305aa593dd03cd0f405c2f93c8a8d1a3601bc7c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 16:35:38 +0200 Subject: [PATCH 0607/1232] Makefile.am: MAINTAINERCLEANFILES+=ar-lib --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 15c04d411e..429befdfa1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -95,7 +95,7 @@ DISTCLEANFILES += include/config.h.in~ MAINTAINERCLEANFILES = INSTALL MAINTAINERCLEANFILES += aclocal.m4 config.guess config.sub MAINTAINERCLEANFILES += configure -MAINTAINERCLEANFILES += depcomp install-sh ltmain.sh test-driver +MAINTAINERCLEANFILES += depcomp install-sh ltmain.sh test-driver ar-lib MAINTAINERCLEANFILES += m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 MAINTAINERCLEANFILES += Makefile.in .dirstamp include/config.h.in From b39474c9c142041d3a44f91eb6635679c6d8ef8f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 16:49:57 +0200 Subject: [PATCH 0608/1232] Update nut.dict --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index b89cf5576a..6b509d7421 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3116 utf-8 +personal_ws-1.1 en 3117 utf-8 AAS ABI ACFAIL @@ -2616,6 +2616,7 @@ repo reposurgeon repotec req +resetter resistive resolv resync From 8078f775e770e8ebb0c44f0153b948c05dcc813a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 16:54:17 +0200 Subject: [PATCH 0609/1232] NEWS: integration with usb_resetter documented [#1887] --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 9718ae1666..d5f56cf269 100644 --- a/NEWS +++ b/NEWS @@ -209,6 +209,11 @@ https://github.com/networkupstools/nut/milestone/8 - upslog: Added support for logging multiple devices with one call to the program [#1604] + - Documentation to integrate NUT USB driver startup with `usb_resetter` script + has been contributed to `scripts/usb_resetter` (the script itself is tracked + externally on GitHub), along with a configuration example for Linux+systemd + [#1887] + - Some fixes applied to Solaris/illumos packaging and SMF service support [#1554, #1564] From b6e9a6b9a14a44129e1c8f8d6bacf2ab31050794 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 31 Mar 2023 19:36:10 +0200 Subject: [PATCH 0610/1232] drivers/nutdrv_qx.c: should we not use correct battery_voltage_reports_one_pack_considered every loop? --- drivers/nutdrv_qx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 095b67c0b4..1285a1daa1 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -38,7 +38,7 @@ * */ -#define DRIVER_VERSION "0.33" +#define DRIVER_VERSION "0.34" #include "config.h" #include "main.h" @@ -3631,6 +3631,7 @@ static bool_t qx_ups_walk(walkmode_t mode) if (mode == QX_WALKMODE_FULL_UPDATE) { batt.runt.act = -1; batt.chrg.act = -1; + battery_voltage_reports_one_pack_considered = 0; } /* Clear data from previous_item */ From 34acab2dd14324d710840188bd60ef6d43a42c8c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 1 Apr 2023 02:44:24 +0200 Subject: [PATCH 0611/1232] drivers/nutdrv_qx_voltronic.c: cover another path to "battery.voltage" with qx_multiply_battvolt() --- 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 e9630588cf..23e932f5c6 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.07" +#define VOLTRONIC_VERSION "Voltronic 0.08" /* Support functions */ static int voltronic_claim(void); @@ -1130,7 +1130,7 @@ static item_t voltronic_qx2nut[] = { * 0 1 2 */ - { "battery.voltage", 0, NULL, "QBV\r", "", 21, '(', "", 1, 5, "%.2f", 0, NULL, NULL, NULL }, + { "battery.voltage", 0, NULL, "QBV\r", "", 21, '(', "", 1, 5, "%.2f", 0, NULL, NULL, qx_multiply_battvolt }, { "battery_number", ST_FLAG_RW, voltronic_r_batt_numb, "QBV\r", "", 21, '(', "", 7, 9, "%d", QX_FLAG_SEMI_STATIC | QX_FLAG_RANGE | QX_FLAG_NONUT, NULL, NULL, voltronic_batt_numb }, /* Number of batteries that make a pack */ { "battery.packs", ST_FLAG_RW, voltronic_r_batt_packs, "QBV\r", "", 21, '(', "", 10, 11, "%.0f", QX_FLAG_SEMI_STATIC | QX_FLAG_RANGE, NULL, NULL, NULL }, /* Number of battery packs in parallel */ { "battery.charge", 0, NULL, "QBV\r", "", 21, '(', "", 13, 15, "%.0f", 0, NULL, NULL, NULL }, From a3d8a5895ccb6701edcf3062292405175c820017 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 1 Apr 2023 15:46:42 +0200 Subject: [PATCH 0612/1232] docs/nut.dict: adapt to newer website preparations --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index b89cf5576a..073e6678a2 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3116 utf-8 +personal_ws-1.1 en 3118 utf-8 AAS ABI ACFAIL @@ -2105,6 +2105,8 @@ jpg jpgraph jre json +jumboinfo +jumbotron kVA kadets kaminski From 424125f6ac427c34afffd20a010047f26d9f2dd0 Mon Sep 17 00:00:00 2001 From: David Martinez Date: Tue, 4 Apr 2023 11:11:46 +0200 Subject: [PATCH 0613/1232] feat: Added support for Salicru SPS 3000 ADV RT2 --- data/driver.list.in | 1 + drivers/salicru-hid.c | 5 +++++ scripts/upower/95-upower-hid.hwdb | 1 + 3 files changed, 7 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 75fe7cab55..e175a6bc4d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1085,6 +1085,7 @@ "Salicru" "ups" "3" "SLC TWINPRO3" "usb" "usbhid-ups (experimental)" "Salicru" "ups" "3" "SLC TWIN RT3" "usb" "usbhid-ups (experimental)" "Salicru" "ups" "3" "SPS 850 ADV T" "usb" "usbhid-ups (experimental)" # https://www.salicru.com/sps-850-adv-t.html https://github.com/networkupstools/nut/issues/1416 +"Salicru" "ups" "3" "SPS 3000 ADV RT2" "usb" "usbhid-ups (experimental)" # https://www.salicru.com/sps-3000-adv-rt2.html "Santak" "ups" "2" "Castle C*K" "Serial" "blazer_ser" # https://github.com/networkupstools/nut/issues/1039 "Santak" "ups" "2" "MT*-PRO" "Serial" "blazer_ser" # https://github.com/networkupstools/nut/issues/1039 diff --git a/drivers/salicru-hid.c b/drivers/salicru-hid.c index 55fe904402..66c5b7df35 100644 --- a/drivers/salicru-hid.c +++ b/drivers/salicru-hid.c @@ -54,6 +54,11 @@ static usb_device_id_t salicru_usb_device_table[] = { /* https://www.salicru.com/sps-850-adv-t.html */ { USB_DEVICE(SALICRU_VENDORID, 0x0302), NULL }, + + /* Salicru SPS 3000 ADV RT2 */ + /* https://www.salicru.com/sps-3000-adv-rt2.html */ + { USB_DEVICE(SALICRU_VENDORID, 0x0101), NULL }, + /* Terminating entry */ { 0, 0, NULL } }; diff --git a/scripts/upower/95-upower-hid.hwdb b/scripts/upower/95-upower-hid.hwdb index 287c3f97fd..c8e6356607 100644 --- a/scripts/upower/95-upower-hid.hwdb +++ b/scripts/upower/95-upower-hid.hwdb @@ -190,6 +190,7 @@ usb:v2E51pFFFF* UPOWER_VENDOR=Ever # Salicru +usb:v2E66p0101* usb:v2E66p0201* usb:v2E66p0202* usb:v2E66p0203* From 7e36b658e5f3ecae6a017974b91f0440d0fd38e0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 4 Apr 2023 11:21:36 +0200 Subject: [PATCH 0614/1232] Update salicru-hid.c Whitespace and alphabetic fixes, subdriver version bump --- drivers/salicru-hid.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/salicru-hid.c b/drivers/salicru-hid.c index 66c5b7df35..717fc841ce 100644 --- a/drivers/salicru-hid.c +++ b/drivers/salicru-hid.c @@ -33,7 +33,7 @@ #include "main.h" /* for getval() */ #include "usb-common.h" -#define SALICRU_HID_VERSION "Salicru HID 0.3" +#define SALICRU_HID_VERSION "Salicru HID 0.4" /* FIXME: experimental flag to be put in upsdrv_info */ /* Salicru */ @@ -41,6 +41,10 @@ /* USB IDs device table */ static usb_device_id_t salicru_usb_device_table[] = { + /* Salicru SPS 3000 ADV RT2 */ + /* https://www.salicru.com/sps-3000-adv-rt2.html */ + { USB_DEVICE(SALICRU_VENDORID, 0x0101), NULL }, + /* TWINPRO3/TWINRT3 (SLC-1500-TWIN PRO3) per https://github.com/networkupstools/nut/issues/1142 */ /* SLC TWIN PRO2<=3KVA per https://github.com/networkupstools/nut/issues/450 */ { USB_DEVICE(SALICRU_VENDORID, 0x0201), NULL }, @@ -50,14 +54,10 @@ static usb_device_id_t salicru_usb_device_table[] = { /* Salicru SPS 850 HOME per https://github.com/networkupstools/nut/pull/1199 */ /* https://www.salicru.com/sps-home.html */ { USB_DEVICE(SALICRU_VENDORID, 0x0300), NULL }, - /* Salicru SPS 850 ADV T, see https://github.com/networkupstools/nut/issues/1416 */ - /* https://www.salicru.com/sps-850-adv-t.html */ - { USB_DEVICE(SALICRU_VENDORID, 0x0302), NULL }, - - /* Salicru SPS 3000 ADV RT2 */ - /* https://www.salicru.com/sps-3000-adv-rt2.html */ - { USB_DEVICE(SALICRU_VENDORID, 0x0101), NULL }, + /* Salicru SPS 850 ADV T, see https://github.com/networkupstools/nut/issues/1416 */ + /* https://www.salicru.com/sps-850-adv-t.html */ + { USB_DEVICE(SALICRU_VENDORID, 0x0302), NULL }, /* Terminating entry */ { 0, 0, NULL } From 6a526a7dbe969b907ae8f7f39a997552af1b25c8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 12 Apr 2023 11:23:39 +0200 Subject: [PATCH 0615/1232] Update README.md Reformatted line widths and code examples, incorporated PR discussion notes --- scripts/usb_resetter/README.md | 90 ++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/scripts/usb_resetter/README.md b/scripts/usb_resetter/README.md index 27e20081fc..d4c09d9cb4 100644 --- a/scripts/usb_resetter/README.md +++ b/scripts/usb_resetter/README.md @@ -3,52 +3,90 @@ File: scripts/usb_resetter/README Date: 30 Mar 2023 Auth: Orsiris de Jong - NetInvent SASU -Some cheaper USB UPS have the same kind of unreliable USB to serial interface, being a Cypress Semiconductor USB to Serial / UNNO TECH USB to Serial. -Most of them use `blazer_usb` driver, and sometimes the driver can't start because it can't communicate with the UPS. +Some cheaper USB UPS have the same kind of unreliable USB to serial interface, +being a "Cypress Semiconductor USB to Serial" or "INNO TECH USB to Serial" +(often with the `0665:5161` VendorID/ProductId seen in examples below). +Most of them use `blazer_usb` or `nutdrv_qx` driver, and sometimes the +driver can't start because it can't communicate with the UPS. + +NOTE: It is believed that in some cases the chip on UPS side can go into a +sort of power-saving mode after some quiet time, so increasing the NUT driver +polling frequency may help avoid that particular situation. Unplugging and plugging the USB port usually fixes this, but that's not convenient. -That's where usb_resetter comes in handy. (see https://github.com/netinvent/usb_resetter for more info) -Grab a copy via pip with `pip install usb_resetter` or make a plain install with -``` -curl -o /usr/local/bin/usb_resetter -L https://raw.githubusercontent.com/netinvent/usb_resetter/main/usb_resetter/usb_resetter.py && chmod +x /usr/local/bin/usb_resetter -``` +That's where `usb_resetter` comes in handy (see https://github.com/netinvent/usb_resetter +project page for more info). You would need a Python environment to run it, and it +is limited to Linux platforms as of this writing. -Once you got the script, identify the USB UPS with +Grab a copy via `pip` with `pip install usb_resetter`, or make a plain install +directly from GitHub with e.g.: +```` +:; curl -o /usr/local/bin/usb_resetter -L \ + https://raw.githubusercontent.com/netinvent/usb_resetter/main/usb_resetter/usb_resetter.py \ + && chmod +x /usr/local/bin/usb_resetter +```` +Once you have got the script, identify the USB UPS with: ``` -usb_resetter --list +:; usb_resetter --list ``` -In our case, we could find something like `Found device 0665:5161 at /dev/bus/usb/001/002 Manufacturer=INNO TECH, Product=USB to Serial` +In our case, we could see something like: +```` +Found device 0665:5161 at /dev/bus/usb/001/002 Manufacturer=INNO TECH, Product=USB to Serial +```` -usb_restter can work in three different ways: +The `usb_resetter` can work in three different ways: - Reset device itself - Reset the hub the device is attached to - Reset all USB controllers -A simple USB device reset isn't sufficient for those UPS devices. - -We'll need to reset the hub it's attached to. +A simple USB device reset typically isn't sufficient for those UPS devices, +so we would need to reset the hub it's attached to. -The command for doing so is: +The command for doing that is: ``` -usb_resetter --reset-hub --device 0665:5161 +:; usb_resetter --reset-hub --device 0665:5161 ``` -Bear in mind that this will reset other devices connected to the same hub. While this isn't a problem for a keyboard / mouse, it might be for a USB storage device. -On some hardware, each USB plug gets it's own hub. On others, two or more USB plus share one hub. -A good practice would be to isolate the USB UPS on a hub without any other device in order to not interfere with other hardware, or associate it on a hub where a non critical device is already plugged. +Bear in mind that this will reset other devices connected to the same hub. +While this isn't a problem for a keyboard / mouse, it might be for a USB +storage device. On some hardware, each USB plug gets it's own hub. +On others, two or more USB plus share one hub. -Getting the hub your device is attached to can be done with: -``` -usb_resetter --list-hubs --device 0665:5161 -``` +A good practice would be to isolate the USB UPS on a hub without any other +device in order to not interfere with other hardware, or to associate it +on a hub where a non-critical device is already plugged. +Getting the hub your device is attached to can be done with: +```` +:; usb_resetter --list-hubs --device 0665:5161 +```` -The easiest way to integrate with nut-driver is to modify the systemd service file with the following line: -``` +The easiest way to integrate this activity with the `nut-driver` service +is to modify the systemd service file (or ideally use a separate "drop-in" +snippet file) with the following line: +```` ExecStartPre=/usr/local/bin/usb_reset.py --reset-hub --device 0665:5161 -``` +```` + +An example modified `nut-driver.service` file which may be applicable to a +NUT v2.7.4 or older release (modulo the paths and the particular VID:PID) +is provided in this directory. Those releases packaged a single service unit +for all the drivers you have, managed as one bundle. + +With current NUT releases (2.8.0+), a `nut-driver@.service` template is used +to run each driver in a dedicated instance, declared manually or often by the +`nut-driver-enumerator` script or service (tracking `ups.conf` sections). +The added call to `usb_resetter` can then be a systemd drop-in file for that +particular device named like `/etc/systemd/system/nut-driver@myups.service.d/dropin.conf`, +so it does not impact others (unless they use the same USB hub). This way, every time the nut-driver service is reloaded, the USB UPS is reset. + +NOTE: In author's testing, there were no additional delays required after +the `usb_resetter` before starting the driver. Generally however, keep in +mind that after a (re-)connection, the OS re-discovers the device, then it +gets owned by kernel, then the udev/upower/... subsystem hands it off to a +NUT run-time account, and only then can it be opened by a driver. From 9935256fabad119de8b36bd3ee4dbe2d77ea0a30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 12 Apr 2023 11:27:39 +0200 Subject: [PATCH 0616/1232] Update README.md Some more formatting/wording fixes --- scripts/usb_resetter/README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/usb_resetter/README.md b/scripts/usb_resetter/README.md index d4c09d9cb4..f1c226e255 100644 --- a/scripts/usb_resetter/README.md +++ b/scripts/usb_resetter/README.md @@ -9,18 +9,20 @@ being a "Cypress Semiconductor USB to Serial" or "INNO TECH USB to Serial" Most of them use `blazer_usb` or `nutdrv_qx` driver, and sometimes the driver can't start because it can't communicate with the UPS. -NOTE: It is believed that in some cases the chip on UPS side can go into a -sort of power-saving mode after some quiet time, so increasing the NUT driver -polling frequency may help avoid that particular situation. +NOTE: It is believed that in some cases the chip on UPS side can go into +a sort of power-saving mode after some quiet time, so increasing the NUT +driver polling frequency may help avoid that particular situation. -Unplugging and plugging the USB port usually fixes this, but that's not convenient. +Unplugging and plugging the USB port usually fixes this, but that's not +convenient. -That's where `usb_resetter` comes in handy (see https://github.com/netinvent/usb_resetter -project page for more info). You would need a Python environment to run it, and it -is limited to Linux platforms as of this writing. +That's where `usb_resetter` comes in handy (see the +https://github.com/netinvent/usb_resetter project page for more info). +You would need a Python environment to run the script, and it is limited +to Linux platforms as of this writing. -Grab a copy via `pip` with `pip install usb_resetter`, or make a plain install -directly from GitHub with e.g.: +Grab a copy via `pip` with `pip install usb_resetter`, or make a plain +install directly from GitHub with e.g.: ```` :; curl -o /usr/local/bin/usb_resetter -L \ https://raw.githubusercontent.com/netinvent/usb_resetter/main/usb_resetter/usb_resetter.py \ @@ -79,11 +81,13 @@ for all the drivers you have, managed as one bundle. With current NUT releases (2.8.0+), a `nut-driver@.service` template is used to run each driver in a dedicated instance, declared manually or often by the `nut-driver-enumerator` script or service (tracking `ups.conf` sections). -The added call to `usb_resetter` can then be a systemd drop-in file for that -particular device named like `/etc/systemd/system/nut-driver@myups.service.d/dropin.conf`, +The added call to `usb_resetter` can then be a systemd drop-in file +tailored for that particular device and named like +`/etc/systemd/system/nut-driver@myups.service.d/dropin.conf`, so it does not impact others (unless they use the same USB hub). -This way, every time the nut-driver service is reloaded, the USB UPS is reset. +This way, every time the nut-driver service is restarted, the USB UPS link +is reset. NOTE: In author's testing, there were no additional delays required after the `usb_resetter` before starting the driver. Generally however, keep in From 6c93953c5616bc54db327f46ba6a5f659d630a30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 09:03:03 +0200 Subject: [PATCH 0617/1232] driver/main.{c,h}: extend internal API with addvar_reloadable() and vartab_t->reloadable field [#1903] --- drivers/main.c | 17 +++++++++++++++-- drivers/main.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 250b811200..d21414d44a 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -299,8 +299,8 @@ int testvar(const char *var) return 0; /* not found */ } -/* callback from driver - create the table for -x/conf entries */ -void addvar(int vartype, const char *name, const char *desc) +/* implement callback from driver - create the table for -x/conf entries */ +static void do_addvar(int vartype, const char *name, const char *desc, int reloadable) { vartab_t *tmp, *last; @@ -318,6 +318,7 @@ void addvar(int vartype, const char *name, const char *desc) tmp->val = NULL; tmp->desc = xstrdup(desc); tmp->found = 0; + tmp->reloadable = reloadable; tmp->next = NULL; if (last) @@ -326,6 +327,18 @@ void addvar(int vartype, const char *name, const char *desc) vartab_h = tmp; } +/* public callback from driver - create the table for -x/conf entries for reloadable values */ +void addvar_reloadable(int vartype, const char *name, const char *desc) +{ + do_addvar(vartype, name, desc, 1); +} + +/* public callback from driver - create the table for -x/conf entries for set-once values */ +void addvar(int vartype, const char *name, const char *desc) +{ + do_addvar(vartype, name, desc, 0); +} + /* handle -x / ups.conf config details that are for this part of the code */ static int main_arg(char *var, char *val) { diff --git a/drivers/main.h b/drivers/main.h index b9583eef2c..a04a4cbe21 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -45,6 +45,7 @@ typedef struct vartab_s { char *val; /* right side of = */ char *desc; /* 40 character description for -h text */ int found; /* set once encountered, for testvar() */ + int reloadable; /* driver reload may redefine this value */ struct vartab_s *next; } vartab_t; @@ -56,6 +57,7 @@ typedef struct vartab_s { /* callback from driver - create the table for future -x entries */ void addvar(int vartype, const char *name, const char *desc); +void addvar_reloadable(int vartype, const char *name, const char *desc); /* subdriver description structure */ typedef struct upsdrv_info_s { From 2ccc8de8771ed2e39b1583a0fb48222000a6b2ae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 11:18:43 +0200 Subject: [PATCH 0618/1232] drivers/main.c: add skeleton handling for reload_flag [#1903] --- drivers/main.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index d21414d44a..ac8dd7aed1 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -70,6 +70,10 @@ static int user_from_cmdline = 0, group_from_cmdline = 0; /* signal handling */ int exit_flag = 0; +/* reload_flag is 0 most of the time (including initial config reading), + * and is briefly 1 when a reload signal is received and is being handled + */ +static int reload_flag = 0; #ifndef DRIVERS_MAIN_WITHOUT_MAIN /* should this driver instance go to background (default) @@ -299,6 +303,117 @@ int testvar(const char *var) return 0; /* not found */ } +/* See if can be (re-)loaded now: either is reloadable by definition, + * or no value has been given to it yet. Returns "-1" if nothing needs to + * be done and that is not a failure (e.g. value not modified so we do not + * care if we may change it or not). + */ +static int testvar_reloadable(const char *var, const char *val, int vartype) +{ + vartab_t *tmp = vartab_h; + + while (tmp) { + if (!strcasecmp(tmp->var, var)) { + /* variable name is known */ + if (val && tmp->val) { + /* a value is already known */ + if (vartype == tmp->vartype && !strcasecmp(tmp->val, val)) { + if (reload_flag) { + upsdebugx(1, "%s: setting '%s' " + "exists and is unmodified", + __func__, var); + } + return -1; /* no-op for caller */ + } else { + /* warn loudly if we are reloading and + * can not change this modified value */ + upsdebugx((reload_flag ? (tmp->reloadable ? 1 : 0) : 1), + "%s: setting '%s' exists and differs: " + "new type bitmask %d vs. %d, " + "new value '%s' vs. '%s'", + __func__, var, + vartype, tmp->vartype, + val, tmp->val); + return ( + (!reload_flag) /* For initial config reads, legacy code trusted what it saw */ + || tmp->reloadable /* set in addvar*() */ + ); + } + } + + /* okay to redefine if not yet defined, or if reload is allowed, + * or if initially loading the configs + */ + return ( + (!reload_flag) + || ((!tmp->found) || tmp->reloadable) + ); + } + tmp = tmp->next; + } + + return 1; /* not found, may (re)load the definition */ +} + +/* Similar to testvar_reloadable() above which is for addvar*() defined + * entries, but for less streamlined stuff defined right here in main.c. + * See if value (probably saved in dstate) can be (re-)loaded now: either + * it is reloadable by parameter definition, or no value has been saved + * into it yet ( is NULL). + * Returns "-1" if nothing needs to be done and that is not a failure + * (e.g. value not modified so we do not care if we may change it or not). + */ +static int testval_reloadable(const char *var, const char *oldval, const char *newval, int reloadable) +{ + /* Nothing saved yet? Okay to store new value! */ + if (!oldval) + return 1; + + /* Should not happen? Or... (commented-away etc.) */ + if (!newval) { + upslogx(LOG_WARNING, "%s: new setting for '%s' is NULL", __func__, var); + return ((!reload_flag) || reloadable); + } + + /* a value is already known, another is desired */ + if (!strcasecmp(oldval, newval)) { + if (reload_flag) { + upsdebugx(1, "%s: setting '%s' " + "exists and is unmodified", + __func__, var); + } + return -1; /* no-op for caller */ + } else { + /* warn loudly if we are reloading and + * can not change this modified value */ + upsdebugx((reload_flag ? (reloadable ? 1 : 0) : 1), + "%s: setting '%s' exists and differs: " + "new value '%s' vs. '%s'", + __func__, var, + newval, oldval); + /* For initial config reads, legacy code trusted what it saw */ + return ((!reload_flag) || reloadable); + } +} + +/* Similar to testvar_reloadable() above which is for addvar*() defined + * entries, but for less streamlined stuff defined right here in main.c. + * See if (by name saved in dstate) can be (re-)loaded now: either + * it is reloadable by parameter definition, or no value has been saved + * into it yet ( is NULL). + * Returns "-1" if nothing needs to be done and that is not a failure + * (e.g. value not modified so we do not care if we may change it or not). + */ +static int testarg_reloadable(const char *var, const char *arg, const char *newval, int reloadable) +{ + /* Keep legacy behavior: not reloading, trust the initial config */ + if (!reload_flag || !arg) + return 1; + + /* Only if reloading, suffer the overhead of lookups: */ + return testval_reloadable(var, dstate_getinfo(arg), newval, reloadable); +} + /* implement callback from driver - create the table for -x/conf entries */ static void do_addvar(int vartype, const char *name, const char *desc, int reloadable) { @@ -709,6 +824,13 @@ void set_exit_flag(int sig) } #ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ +static void set_reload_flag(int sig) +{ + NUT_UNUSED_VARIABLE(sig); + reload_flag = 1; +} + # ifndef DRIVERS_MAIN_WITHOUT_MAIN static # endif /* DRIVERS_MAIN_WITHOUT_MAIN */ @@ -719,11 +841,13 @@ void setup_signals(void) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; + /* handle shutdown signals */ sa.sa_handler = set_exit_flag; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); + /* basic signal setup to ignore SIGPIPE */ #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstrict-prototypes" @@ -732,8 +856,11 @@ void setup_signals(void) #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES) # pragma GCC diagnostic pop #endif - sigaction(SIGHUP, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); + + /* handle reloading */ + sa.sa_handler = set_reload_flag; + sigaction(SIGHUP, &sa, NULL); } #endif /* WIN32*/ @@ -1268,6 +1395,15 @@ int main(int argc, char **argv) /* repeat until time is up or extrafd has data */ } } + + if (reload_flag && !exit_flag) { + dstate_setinfo("driver.state", "reloading"); + upsnotify(NOTIFY_STATE_RELOADING, NULL); + /* TODO: Call actual config reloading activity */ + reload_flag = 0; + dstate_setinfo("driver.state", "quiet"); + upsnotify(NOTIFY_STATE_READY, NULL); + } } /* if we get here, the exit flag was set by a signal handler */ From 5f5513c78a6aeee68d637c6226ca92cb8c6b3d50 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 12:46:42 +0200 Subject: [PATCH 0619/1232] drivers/main.{c,h}: make testvar_reloadable(), testval_reloadable(), testinfo_reloadable() a public API in case drivers would need to know [#1903] --- drivers/main.c | 16 ++++++++-------- drivers/main.h | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index ac8dd7aed1..04efa9a734 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -308,7 +308,7 @@ int testvar(const char *var) * be done and that is not a failure (e.g. value not modified so we do not * care if we may change it or not). */ -static int testvar_reloadable(const char *var, const char *val, int vartype) +int testvar_reloadable(const char *var, const char *val, int vartype) { vartab_t *tmp = vartab_h; @@ -363,7 +363,7 @@ static int testvar_reloadable(const char *var, const char *val, int vartype) * Returns "-1" if nothing needs to be done and that is not a failure * (e.g. value not modified so we do not care if we may change it or not). */ -static int testval_reloadable(const char *var, const char *oldval, const char *newval, int reloadable) +int testval_reloadable(const char *var, const char *oldval, const char *newval, int reloadable) { /* Nothing saved yet? Okay to store new value! */ if (!oldval) @@ -398,20 +398,20 @@ static int testval_reloadable(const char *var, const char *oldval, const char *n /* Similar to testvar_reloadable() above which is for addvar*() defined * entries, but for less streamlined stuff defined right here in main.c. - * See if (by name saved in dstate) can be (re-)loaded now: either - * it is reloadable by parameter definition, or no value has been saved - * into it yet ( is NULL). + * See if (by name saved in dstate) can be (re-)loaded now: + * either it is reloadable by parameter definition, or no value has been + * saved into it yet ( is NULL). * Returns "-1" if nothing needs to be done and that is not a failure * (e.g. value not modified so we do not care if we may change it or not). */ -static int testarg_reloadable(const char *var, const char *arg, const char *newval, int reloadable) +int testinfo_reloadable(const char *var, const char *infoname, const char *newval, int reloadable) { /* Keep legacy behavior: not reloading, trust the initial config */ - if (!reload_flag || !arg) + if (!reload_flag || !infoname) return 1; /* Only if reloading, suffer the overhead of lookups: */ - return testval_reloadable(var, dstate_getinfo(arg), newval, reloadable); + return testval_reloadable(var, dstate_getinfo(infoname), newval, reloadable); } /* implement callback from driver - create the table for -x/conf entries */ diff --git a/drivers/main.h b/drivers/main.h index a04a4cbe21..39dd408858 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -59,6 +59,30 @@ typedef struct vartab_s { void addvar(int vartype, const char *name, const char *desc); void addvar_reloadable(int vartype, const char *name, const char *desc); +/* Several helpers for driver configuration reloading follow: + * * testval_reloadable() checks if we are currently reloading (or initially + * loading) the configuration, and if strings oldval==newval or not, + * e.g. for values saved straight into driver source code variables; + * * testinfo_reloadable() checks this for a name saved as dstate_setinfo(); + * * testvar_reloadable() checks in vartab_t list as maintained by addvar(). + * + * All these methods check if value can be (re-)loaded now: + * * either it is reloadable by argument or vartab_t definition, + * * or no value has been saved into it yet (e.g. is NULL), + * * or we are handling initial loading and keep legacy behavior of trusting + * the inputs (e.g. some values may be defined as defaults in global section + * and tuned in a driver section). + * + * Return values: + * * -1 -- if nothing needs to be done and that is not a failure + * (e.g. value not modified so we do not care if we may change it or not); + * * 0 -- if can not modify this value (but it did change in config); + * * 1 -- if we can and should apply a new (maybe initial) value. + */ +int testvar_reloadable(const char *var, const char *val, int vartype); +int testval_reloadable(const char *var, const char *oldval, const char *newval, int reloadable); +int testinfo_reloadable(const char *var, const char *infoname, const char *newval, int reloadable); + /* subdriver description structure */ typedef struct upsdrv_info_s { const char *name; /* driver full name, for banner printing, ... */ From bd59a816c10e56c91efffdebde762f07203ee651 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 12:58:45 +0200 Subject: [PATCH 0620/1232] drivers/main.c: testvar_reloadable(), testval_reloadable(): clarify if the driver must be restarted to apply a value change [#1903] --- drivers/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 04efa9a734..c15516ec9c 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -330,10 +330,13 @@ int testvar_reloadable(const char *var, const char *val, int vartype) upsdebugx((reload_flag ? (tmp->reloadable ? 1 : 0) : 1), "%s: setting '%s' exists and differs: " "new type bitmask %d vs. %d, " - "new value '%s' vs. '%s'", + "new value '%s' vs. '%s'%s", __func__, var, vartype, tmp->vartype, - val, tmp->val); + val, tmp->val, + ((!reload_flag || tmp->reloadable) ? "" : + " (driver restart is needed to apply)") + ); return ( (!reload_flag) /* For initial config reads, legacy code trusted what it saw */ || tmp->reloadable /* set in addvar*() */ @@ -388,9 +391,12 @@ int testval_reloadable(const char *var, const char *oldval, const char *newval, * can not change this modified value */ upsdebugx((reload_flag ? (reloadable ? 1 : 0) : 1), "%s: setting '%s' exists and differs: " - "new value '%s' vs. '%s'", + "new value '%s' vs. '%s'%s", __func__, var, - newval, oldval); + newval, oldval, + ((!reload_flag || reloadable) ? "" : + " (driver restart is needed to apply)") + ); /* For initial config reads, legacy code trusted what it saw */ return ((!reload_flag) || reloadable); } From f53f6b0348992249e0785ce71d620c2f4fedcd41 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 14:35:06 +0200 Subject: [PATCH 0621/1232] drivers/main.c: move pollinterval handling from do_upsconf_args() to main_arg() --- drivers/main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index c15516ec9c..fedebacdd1 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -533,7 +533,19 @@ static int main_arg(char *var, char *val) } /* allow per-driver overrides of the global setting */ - if (!strcmp(var, "synchronous")) { + if (!strcmp(var, "pollinterval")) { + int ipv = atoi(val); + if (ipv > 0) { + poll_interval = (time_t)ipv; + } else { + fatalx(EXIT_FAILURE, "Error: UPS [%s]: invalid pollinterval: %d", + confupsname, ipv); + } + return 1; /* handled */ + } + + /* allow per-driver overrides of the global setting */ + if (!strcmp(var, "synchronous") { if (!strcmp(val, "yes")) do_synchronous=1; else @@ -699,18 +711,6 @@ void do_upsconf_args(char *confupsname, char *var, char *val) return; } - /* allow per-driver overrides of the global setting */ - if (!strcmp(var, "pollinterval")) { - int ipv = atoi(val); - if (ipv > 0) { - poll_interval = (time_t)ipv; - } else { - fatalx(EXIT_FAILURE, "Error: UPS [%s]: invalid pollinterval: %d", - confupsname, ipv); - } - return; - } - /* everything else must be for the driver */ storeval(var, val); } From 86f86cae96b6a4a62e7191d84b1082524dfc5f0d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 13:31:28 +0200 Subject: [PATCH 0622/1232] drivers/main.c: do_global_args(), main_arg(): respect reload_flag [#1903] --- drivers/main.c | 153 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 124 insertions(+), 29 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index fedebacdd1..fc3468e257 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -470,13 +470,20 @@ static int main_arg(char *var, char *val) var ? var : "", /* null should not happen... but... */ val ? val : ""); - if (!strcmp(var, "nolock")) { + /* !reload_flag quietly forbids changing this flag on the fly, as + * it would have no effect anyway without a (serial) reconnection + */ + if (!strcmp(var, "nolock") && !reload_flag) { do_lock_port = 0; dstate_setinfo("driver.flag.nolock", "enabled"); return 1; /* handled */ } - if (!strcmp(var, "ignorelb")) { + /* FIXME: this one we could potentially reload, but need to figure + * out that the flag line was commented away or deleted -- there is + * no setting value to flip in configs here + */ + if (!strcmp(var, "ignorelb") && !reload_flag) { dstate_setinfo("driver.flag.ignorelb", "enabled"); return 1; /* handled */ } @@ -485,9 +492,14 @@ static int main_arg(char *var, char *val) if (!val) return 0; /* unhandled, pass it through to the driver */ + /* In checks below, testinfo_reloadable(..., 0) should forbid + * re-population of the setting with a new value, but emit a + * warning if it did change (so driver restart is needed to apply) + */ + /* variables for main: port */ - if (!strcmp(var, "port")) { + if (!strcmp(var, "port") && testinfo_reloadable(var, "driver.parameter.port", val, 0) > 0) { device_path = xstrdup(val); device_name = xbasename(device_path); dstate_setinfo("driver.parameter.port", "%s", val); @@ -497,7 +509,7 @@ static int main_arg(char *var, char *val) /* user specified at the driver level overrides that on global level * or the built-in default */ - if (!strcmp(var, "user")) { + if (!strcmp(var, "user") && testval_reloadable(var, user, val, 0) > 0) { if (user_from_cmdline) { upsdebugx(0, "User '%s' specified in driver section " "was ignored due to '%s' specified on command line", @@ -512,7 +524,7 @@ static int main_arg(char *var, char *val) return 1; /* handled */ } - if (!strcmp(var, "group")) { + if (!strcmp(var, "group") && testval_reloadable(var, group, val, 0) > 0) { if (group_from_cmdline) { upsdebugx(0, "Group '%s' specified in driver section " "was ignored due to '%s' specified on command line", @@ -532,20 +544,52 @@ static int main_arg(char *var, char *val) return 1; /* handled */ } - /* allow per-driver overrides of the global setting */ + /* Allow per-driver overrides of the global setting + * and allow to reload this, why not. + * Note: having both global+driver section definitions may + * cause noise, but it allows either to be commented away + * and the other to take hold. Both disappearing would not + * be noticed by the reload operation currently, however. + */ if (!strcmp(var, "pollinterval")) { - int ipv = atoi(val); - if (ipv > 0) { - poll_interval = (time_t)ipv; - } else { - fatalx(EXIT_FAILURE, "Error: UPS [%s]: invalid pollinterval: %d", - confupsname, ipv); + int do_handle = 1; + char buf[SMALLBUF]; + + /* log a message if value changed; skip if no good buf */ + if (snprintf(buf, sizeof(buf), "%" PRIdMAX, (intmax_t)poll_interval)) { + if ((do_handle = testval_reloadable(var, buf, val, 1)) == 0) { + /* Should not happen, but... */ + fatalx(EXIT_FAILURE, "Error: failed to check " + "testval_reloadable() for pollinterval: " + "old %s vs. new %s", buf, NUT_STRARG(val)); + } } + + if (do_handle > 0) { + int ipv = atoi(val); + if (ipv > 0) { + poll_interval = (time_t)ipv; + } else { + fatalx(EXIT_FAILURE, "Error: UPS [%s]: invalid pollinterval: %d", + NUT_STRARG(upsname), ipv); + } + } /* else: no-op */ + return 1; /* handled */ } - /* allow per-driver overrides of the global setting */ - if (!strcmp(var, "synchronous") { + /* Allow per-driver overrides of the global setting + * and allow to reload this, why not. + * Note: this may cause "spurious" redefinitions of the + * "no" setting which is the fallback for random values. + * Also note that global+driver section definitions may + * cause noise, but it allows either to be commented away + * and the other to take hold. Both disappearing would not + * be noticed by the reload operation currently, however. + */ + if (!strcmp(var, "synchronous") + && testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0 + ) { if (!strcmp(val, "yes")) do_synchronous=1; else @@ -583,27 +627,50 @@ static int main_arg(char *var, char *val) static void do_global_args(const char *var, const char *val) { + char buf[SMALLBUF]; + upsdebugx(3, "%s: var='%s' val='%s'", __func__, var ? var : "", /* null should not happen... but... */ val ? val : ""); + /* Allow to reload this, why not */ if (!strcmp(var, "pollinterval")) { - int ipv = atoi(val); - if (ipv > 0) { - poll_interval = (time_t)ipv; - } else { - fatalx(EXIT_FAILURE, "Error: invalid pollinterval: %d", ipv); + int do_handle = 1; + + /* log a message if value changed; skip if no good buf */ + if (snprintf(buf, sizeof(buf), "%" PRIdMAX, (intmax_t)poll_interval)) { + if ((do_handle = testval_reloadable(var, buf, val, 1)) == 0) { + /* Should not happen, but... */ + fatalx(EXIT_FAILURE, "Error: failed to check " + "testval_reloadable() for pollinterval: " + "old %s vs. new %s", buf, val); + } } + + if (do_handle > 0) { + int ipv = atoi(val); + if (ipv > 0) { + poll_interval = (time_t)ipv; + } else { + fatalx(EXIT_FAILURE, "Error: invalid pollinterval: %d", ipv); + } + } /* else: no-op */ + return; } - if (!strcmp(var, "chroot")) { + /* In checks below, testinfo_reloadable(..., 0) should forbid + * re-population of the setting with a new value, but emit a + * warning if it did change (so driver restart is needed to apply) + */ + + if (!strcmp(var, "chroot") && testval_reloadable(var, chroot_path, val, 0) > 0) { free(chroot_path); chroot_path = xstrdup(val); } - if (!strcmp(var, "user")) { + if (!strcmp(var, "user") && testval_reloadable(var, user, val, 0) > 0) { if (user_from_cmdline) { upsdebugx(0, "User specified in global section '%s' " "was ignored due to '%s' specified on command line", @@ -617,7 +684,7 @@ static void do_global_args(const char *var, const char *val) } } - if (!strcmp(var, "group")) { + if (!strcmp(var, "group") && testval_reloadable(var, group, val, 0) > 0) { if (group_from_cmdline) { upsdebugx(0, "Group specified in global section '%s' " "was ignored due to '%s' specified on command line", @@ -631,7 +698,17 @@ static void do_global_args(const char *var, const char *val) } } - if (!strcmp(var, "synchronous")) { + /* Allow to reload this, why not + * Note: this may cause "spurious" redefinitions of the + * "no" setting which is the fallback for random values. + * Also note that global+driver section definitions may + * cause noise, but it allows either to be commented away + * and the other to take hold. Both disappearing would not + * be noticed by the reload operation currently, however. + */ + if (!strcmp(var, "synchronous") + && testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0 + ) { if (!strcmp(val, "yes")) do_synchronous=1; else @@ -677,17 +754,29 @@ void do_upsconf_args(char *confupsname, char *var, char *val) /* flags (no =) now get passed to the driver-level stuff */ if (!val) { - /* also store this, but it's a bit different */ snprintf(tmp, sizeof(tmp), "driver.flag.%s", var); - dstate_setinfo(tmp, "enabled"); - storeval(var, NULL); + /* allow reloading if defined and permitted via addvar() + * or not defined there (FIXME?) + */ + if (testvar_reloadable(var, NULL, VAR_FLAG) > 0) { + dstate_setinfo(tmp, "enabled"); + storeval(var, NULL); + } + return; } - /* don't let the user shoot themselves in the foot */ - if (!strcmp(var, "driver")) { + /* In checks below, testval_reloadable(..., 0) should forbid + * re-population of the setting with a new value, but emit a + * warning if it did change (so driver restart is needed to apply) + */ + + /* don't let the user shoot themselves in the foot + * reload should not allow changes here, but would report + */ + if (!strcmp(var, "driver") && testval_reloadable(var, progname, val, 0) > 0) { /* Accomodate for libtool wrapped developer iterations * running e.g. `drivers/.libs/lt-dummy-ups` filenames */ @@ -712,7 +801,13 @@ void do_upsconf_args(char *confupsname, char *var, char *val) } /* everything else must be for the driver */ - storeval(var, val); + + /* allow reloading if defined and permitted via addvar() + * or not defined there (FIXME?) + */ + if (testvar_reloadable(var, val, VAR_VALUE) > 0) { + storeval(var, val); + } } #ifndef DRIVERS_MAIN_WITHOUT_MAIN From d9384789196bf570b76b8a8592c9a5c79d4bb447 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 13:44:38 +0200 Subject: [PATCH 0623/1232] drivers/main.c: refactor assign_debug_level() --- drivers/main.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index fc3468e257..9b05dc0f7b 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -810,6 +810,27 @@ void do_upsconf_args(char *confupsname, char *var, char *val) } } +static void assign_debug_level(void) { + /* CLI debug level can not be smaller than debug_min specified + * in ups.conf, and value specified for a driver config section + * overrides the global one. Note that non-zero debug_min does + * not impact foreground running mode. + */ + int nut_debug_level_upsconf = -1; + + if (nut_debug_level_global >= 0 && nut_debug_level_driver >= 0) { + nut_debug_level_upsconf = nut_debug_level_driver; + } else { + if (nut_debug_level_global >= 0) nut_debug_level_upsconf = nut_debug_level_global; + if (nut_debug_level_driver >= 0) nut_debug_level_upsconf = nut_debug_level_driver; + } + + if (nut_debug_level_upsconf > nut_debug_level) + nut_debug_level = nut_debug_level_upsconf; + + upsdebugx(1, "debug level is '%d'", nut_debug_level); +} + #ifndef DRIVERS_MAIN_WITHOUT_MAIN /* split -x foo=bar into 'foo' and 'bar' */ static void splitxarg(char *inbuf) @@ -1166,23 +1187,7 @@ int main(int argc, char **argv) "Try -h for help."); } - /* CLI debug level can not be smaller than debug_min specified - * in ups.conf, and value specified for a driver config section - * overrides the global one. Note that non-zero debug_min does - * not impact foreground running mode. - */ - { - int nut_debug_level_upsconf = -1 ; - if ( nut_debug_level_global >= 0 && nut_debug_level_driver >= 0 ) { - nut_debug_level_upsconf = nut_debug_level_driver; - } else { - if ( nut_debug_level_global >= 0 ) nut_debug_level_upsconf = nut_debug_level_global; - if ( nut_debug_level_driver >= 0 ) nut_debug_level_upsconf = nut_debug_level_driver; - } - if ( nut_debug_level_upsconf > nut_debug_level ) - nut_debug_level = nut_debug_level_upsconf; - } - upsdebugx(1, "debug level is '%d'", nut_debug_level); + assign_debug_level(); new_uid = get_user_pwent(user); From 7111d16e5dbc7cc8d31cffc7594ff259139e5587 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 14:03:00 +0200 Subject: [PATCH 0624/1232] drivers/main.c: introduce (and honour) nut_debug_level_args [#1903] --- drivers/main.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 9b05dc0f7b..4c0911fbbf 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -95,6 +95,7 @@ static int background_flag = -1; * value less than that would not have effect, can only * have more). */ +static int nut_debug_level_args = -1; static int nut_debug_level_global = -1; static int nut_debug_level_driver = -1; @@ -820,11 +821,41 @@ static void assign_debug_level(void) { if (nut_debug_level_global >= 0 && nut_debug_level_driver >= 0) { nut_debug_level_upsconf = nut_debug_level_driver; + if (reload_flag) { + upslogx(LOG_INFO, + "Applying debug_min=%d from ups.conf" + " driver section (overriding global)", + nut_debug_level_upsconf); + } } else { - if (nut_debug_level_global >= 0) nut_debug_level_upsconf = nut_debug_level_global; - if (nut_debug_level_driver >= 0) nut_debug_level_upsconf = nut_debug_level_driver; + if (nut_debug_level_global >= 0) { + nut_debug_level_upsconf = nut_debug_level_global; + if (reload_flag) upslogx(LOG_INFO, + "Applying debug_min=%d from ups.conf" + " global section", + nut_debug_level_upsconf); + } + if (nut_debug_level_driver >= 0) { + nut_debug_level_upsconf = nut_debug_level_driver; + if (reload_flag) upslogx(LOG_INFO, + "Applying debug_min=%d from ups.conf" + " driver section", + nut_debug_level_upsconf); + } } + if (reload_flag && nut_debug_level_upsconf == -1) { + /* DEBUG_MIN is absent or commented-away in ups.conf */ + upslogx(LOG_INFO, + "Applying debug level %d from " + "original command line arguments", + nut_debug_level_args); + } + + /* at minimum, the verbosity we started with - via CLI arguments; + * maybe a greater debug_min is set in current config file + */ + nut_debug_level = nut_debug_level_args; if (nut_debug_level_upsconf > nut_debug_level) nut_debug_level = nut_debug_level_upsconf; @@ -996,6 +1027,9 @@ int main(int argc, char **argv) int i, do_forceshutdown = 0; int update_count = 0; + /* init verbosity from default in common.c (0 probably) */ + nut_debug_level_args = nut_debug_level; + dstate_setinfo("driver.state", "init.starting"); atexit(exit_cleanup); @@ -1067,7 +1101,9 @@ int main(int argc, char **argv) background_flag = 1; break; case 'D': + /* bump right here, may impact reporting of other CLI args */ nut_debug_level++; + nut_debug_level_args++; break; case 'd': dump_data = atoi(optarg); From 29fd9fdc39139362765e43fd6df937b363dd1611 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 15:27:47 +0200 Subject: [PATCH 0625/1232] drivers/main.c: testvar_reloadable(): handle known flags conservatively [#1903] --- drivers/main.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 4c0911fbbf..1fcfa60f69 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -313,18 +313,43 @@ int testvar_reloadable(const char *var, const char *val, int vartype) { vartab_t *tmp = vartab_h; + /* FIXME: handle VAR_FLAG typed (bitmask) values specially somehow? + * Either we set the flag at some point (because its name is mentioned) + * or we do not (initially set - no way so far to know it got commented + * away before a reload on the fly). Might load new config info into a + * separate list and then compare missing points?.. + */ + while (tmp) { if (!strcasecmp(tmp->var, var)) { /* variable name is known */ if (val && tmp->val) { - /* a value is already known */ - if (vartype == tmp->vartype && !strcasecmp(tmp->val, val)) { - if (reload_flag) { - upsdebugx(1, "%s: setting '%s' " - "exists and is unmodified", - __func__, var); + /* a value is already known by name + * and bitmask for VAR_FLAG/VAR_VALUE matches + */ + if (vartype && tmp->vartype) { + if ((tmp->vartype & VAR_FLAG) && val == NULL) { + if (reload_flag) { + upsdebugx(1, "%s: setting '%s' " + "exists and is a flag; " + "new value was not specified", + __func__, var); + } + + /* by default: apply flags initially, ignore later */ + return ( + (!reload_flag) /* For initial config reads, legacy code trusted what it saw */ + || tmp->reloadable /* set in addvar*() */ + ); + } + if (!strcasecmp(tmp->val, val)) { + if (reload_flag) { + upsdebugx(1, "%s: setting '%s' " + "exists and is unmodified", + __func__, var); + } + return -1; /* no-op for caller */ } - return -1; /* no-op for caller */ } else { /* warn loudly if we are reloading and * can not change this modified value */ @@ -417,7 +442,14 @@ int testinfo_reloadable(const char *var, const char *infoname, const char *newva if (!reload_flag || !infoname) return 1; - /* Only if reloading, suffer the overhead of lookups: */ + /* Suffer the overhead of lookups only if reloading */ + + /* FIXME: handle "driver.flag.*" prefixed values specially somehow? + * Either we set the flag at some point (because its name is mentioned) + * or we do not (initially set - no way so far to know it got commented + * away before a reload on the fly). Might load new config info into a + * separate list and then compare missing points?.. + */ return testval_reloadable(var, dstate_getinfo(infoname), newval, reloadable); } From d8f97d39149932d0b0e43c73da624d7bbe96c7a4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 15:54:57 +0200 Subject: [PATCH 0626/1232] drivers/main.c: pepper test*_reloadable() and do_upsconf_args() with upsdebugx() [#1903] --- drivers/main.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 1fcfa60f69..0310625104 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -319,10 +319,18 @@ int testvar_reloadable(const char *var, const char *val, int vartype) * away before a reload on the fly). Might load new config info into a * separate list and then compare missing points?.. */ + upsdebugx(6, "%s: searching for var=%s, vartype=%d, reload_flag=%d", + __func__, NUT_STRARG(var), vartype, reload_flag); while (tmp) { if (!strcasecmp(tmp->var, var)) { /* variable name is known */ + upsdebugx(6, "%s: found var=%s, val='%s' => '%s', vartype=%d => %d, found=%d, reloadable=%d, reload_flag=%d", + __func__, NUT_STRARG(var), + NUT_STRARG(tmp->val), NUT_STRARG(val), + tmp->vartype, vartype, + tmp->found, tmp->reloadable, reload_flag); + if (val && tmp->val) { /* a value is already known by name * and bitmask for VAR_FLAG/VAR_VALUE matches @@ -394,6 +402,10 @@ int testvar_reloadable(const char *var, const char *val, int vartype) */ int testval_reloadable(const char *var, const char *oldval, const char *newval, int reloadable) { + upsdebugx(6, "%s: var=%s, oldval=%s, newval=%s, reloadable=%d, reload_flag=%d", + __func__, NUT_STRARG(var), NUT_STRARG(oldval), NUT_STRARG(newval), + reloadable, reload_flag); + /* Nothing saved yet? Okay to store new value! */ if (!oldval) return 1; @@ -438,6 +450,10 @@ int testval_reloadable(const char *var, const char *oldval, const char *newval, */ int testinfo_reloadable(const char *var, const char *infoname, const char *newval, int reloadable) { + upsdebugx(6, "%s: var=%s, infoname=%s, newval=%s, reloadable=%d, reload_flag=%d", + __func__, NUT_STRARG(var), NUT_STRARG(infoname), NUT_STRARG(newval), + reloadable, reload_flag); + /* Keep legacy behavior: not reloading, trust the initial config */ if (!reload_flag || !infoname) return 1; @@ -770,8 +786,12 @@ void do_upsconf_args(char *confupsname, char *var, char *val) { char tmp[SMALLBUF]; + upsdebugx(5, "%s: confupsname=%s, var=%s, val=%s", + __func__, NUT_STRARG(confupsname), NUT_STRARG(var), NUT_STRARG(val)); + /* handle global declarations */ if (!confupsname) { + upsdebugx(5, "%s: call do_global_args()", __func__); do_global_args(var, val); return; } @@ -782,11 +802,15 @@ void do_upsconf_args(char *confupsname, char *var, char *val) upsname_found = 1; + upsdebugx(5, "%s: call main_arg()", __func__); if (main_arg(var, val)) return; + upsdebugx(5, "%s: not a main_arg()", __func__); /* flags (no =) now get passed to the driver-level stuff */ if (!val) { + upsdebugx(5, "%s: process as flag", __func__); + /* also store this, but it's a bit different */ snprintf(tmp, sizeof(tmp), "driver.flag.%s", var); @@ -838,6 +862,7 @@ void do_upsconf_args(char *confupsname, char *var, char *val) /* allow reloading if defined and permitted via addvar() * or not defined there (FIXME?) */ + upsdebugx(5, "%s: process as value", __func__); if (testvar_reloadable(var, val, VAR_VALUE) > 0) { storeval(var, val); } From 1252093b4973dd830c1dfa046b03686bceb1b176 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 15:55:44 +0200 Subject: [PATCH 0627/1232] drivers/main.c: do_upsconf_args(): fix handling of "driver" value [#1903] --- drivers/main.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 0310625104..bd04d98f0a 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -833,21 +833,36 @@ void do_upsconf_args(char *confupsname, char *var, char *val) /* don't let the user shoot themselves in the foot * reload should not allow changes here, but would report */ - if (!strcmp(var, "driver") && testval_reloadable(var, progname, val, 0) > 0) { - /* Accomodate for libtool wrapped developer iterations - * running e.g. `drivers/.libs/lt-dummy-ups` filenames + if (!strcmp(var, "driver")) { + int do_handle; + + upsdebugx(5, "%s: this is a 'driver' setting, may we proceed?", __func__); + do_handle = testval_reloadable(var, progname, val, 0); + + if (do_handle == -1) { + upsdebugx(5, "%s: 'driver' setting already applied with this value", __func__); + return; + } + + /* Acceptable progname is only set once during start-up + * val is from ups.conf */ - size_t tmplen = strlen("lt-"); - if (strncmp("lt-", progname, tmplen) == 0 - && strcmp(val, progname + tmplen) == 0) { - /* debug level may be not initialized yet, and situation - * should not happen in end-user builds, so ok to yell: */ - upsdebugx(0, "Seems this driver binary %s is a libtool " - "wrapped build for driver %s", progname, val); - /* progname points to xbasename(argv[0]) in-place; - * roll the pointer forward a bit, we know we can: + if (!reload_flag || do_handle > 0) { + /* Accomodate for libtool wrapped developer iterations + * running e.g. `drivers/.libs/lt-dummy-ups` filenames */ - progname = progname + tmplen; + size_t tmplen = strlen("lt-"); + if (strncmp("lt-", progname, tmplen) == 0 + && strcmp(val, progname + tmplen) == 0) { + /* debug level may be not initialized yet, and situation + * should not happen in end-user builds, so ok to yell: */ + upsdebugx(0, "Seems this driver binary %s is a libtool " + "wrapped build for driver %s", progname, val); + /* progname points to xbasename(argv[0]) in-place; + * roll the pointer forward a bit, we know we can: + */ + progname = progname + tmplen; + } } if (strcmp(val, progname) != 0) { From c910b81d8df066b2021d380419e4558b0e7ac9e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 16:02:11 +0200 Subject: [PATCH 0628/1232] drivers/main.c: upsdebugx() raising the flags due to signals (exit, reload) [#1903] --- drivers/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index bd04d98f0a..d1e79c2f08 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1045,6 +1045,7 @@ static void exit_cleanup(void) void set_exit_flag(int sig) { + upsdebugx(1, "%s: raising exit flag due to signal %d", __func__, sig); exit_flag = sig; } @@ -1052,7 +1053,7 @@ void set_exit_flag(int sig) /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ static void set_reload_flag(int sig) { - NUT_UNUSED_VARIABLE(sig); + upsdebugx(1, "%s: raising reload flag due to signal %d", __func__, sig); reload_flag = 1; } From bfefaed283be4c5f4d9af9d892d5acd614f5469c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 17:56:29 +0200 Subject: [PATCH 0629/1232] drivers/main.c: always setup_signals() if we are not a one-shot run (fore- or back-ground) --- drivers/main.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index d1e79c2f08..e4c1f7ceda 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1309,15 +1309,20 @@ int main(int argc, char **argv) * or not just dumping data (for discovery) */ /* This avoids case where ie /var is unmounted already */ #ifndef WIN32 - if ((!do_forceshutdown) && (!dump_data) && (chdir(dflt_statepath()))) - fatal_with_errno(EXIT_FAILURE, "Can't chdir to %s", dflt_statepath()); + if ((!do_forceshutdown) && (!dump_data)) { + if (chdir(dflt_statepath())) + fatal_with_errno(EXIT_FAILURE, "Can't chdir to %s", dflt_statepath()); - /* Setup signals to communicate with driver once backgrounded. */ + /* Setup signals to communicate with driver which is destined for a long run. */ + setup_signals(); + } + + /* Setup PID file to receive signals to communicate with this driver + * instance once backgrounded, and to stop a competing older instance. + */ if ((background_flag != 0) && (!do_forceshutdown)) { char buffer[SMALLBUF]; - setup_signals(); - snprintf(buffer, sizeof(buffer), "%s/%s-%s.pid", altpidpath(), progname, upsname); /* Try to prevent that driver is started multiple times. If a PID file */ From 218e52e22598c1329c4fced0c7e5563a11448782 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 17:56:55 +0200 Subject: [PATCH 0630/1232] drivers/main.c: actually read_upsconf() to handle reload (SIGHUP) [#1903] --- drivers/main.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index e4c1f7ceda..a96b73ff74 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1617,12 +1617,36 @@ int main(int argc, char **argv) } if (reload_flag && !exit_flag) { + upslogx(LOG_INFO, "Handling requested live reload of NUT driver configuration"); dstate_setinfo("driver.state", "reloading"); upsnotify(NOTIFY_STATE_RELOADING, NULL); - /* TODO: Call actual config reloading activity */ + + /* If commented away or deleted in config, debug_min + * should "disappear" for us (a CLI argument, if any, + * would still be honoured); if it is (re-)defined in + * config, then it gets considered. + */ + nut_debug_level_global = -1; + nut_debug_level_driver = -1; + + /* Call actual config reloading activity */ + read_upsconf(); + /* TODO: Callbacks in drivers to re-parse configs? + * Currently this reloadability relies on either + * explicit reload_flag aware code called from the + * read_upsconf() method, or on drivers continuously + * reading dstate_getinfo() and not caching once + * their C variables. + */ + + /* Re-mix currently known debug verbosity desires */ + assign_debug_level(); + + /* Wrap it up */ reload_flag = 0; dstate_setinfo("driver.state", "quiet"); upsnotify(NOTIFY_STATE_READY, NULL); + upslogx(LOG_INFO, "Completed requested live reload of NUT driver configuration"); } } From ca191282adc2ff00767449e68e99c07fa0aa5f90 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 18:23:34 +0200 Subject: [PATCH 0631/1232] drivers/main.c: fix do_global_args() and main_arg() to not ignore unmodified settings during reload [#1903] --- drivers/main.c | 180 ++++++++++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 76 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index a96b73ff74..cc0484ad24 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -512,6 +512,8 @@ void addvar(int vartype, const char *name, const char *desc) /* handle -x / ups.conf config details that are for this part of the code */ static int main_arg(char *var, char *val) { + int do_handle = -2; + /* flags for main */ upsdebugx(3, "%s: var='%s' val='%s'", @@ -548,42 +550,48 @@ static int main_arg(char *var, char *val) /* variables for main: port */ - if (!strcmp(var, "port") && testinfo_reloadable(var, "driver.parameter.port", val, 0) > 0) { - device_path = xstrdup(val); - device_name = xbasename(device_path); - dstate_setinfo("driver.parameter.port", "%s", val); + if (!strcmp(var, "port")) { + if (testinfo_reloadable(var, "driver.parameter.port", val, 0) > 0) { + device_path = xstrdup(val); + device_name = xbasename(device_path); + dstate_setinfo("driver.parameter.port", "%s", val); + } return 1; /* handled */ } /* user specified at the driver level overrides that on global level * or the built-in default */ - if (!strcmp(var, "user") && testval_reloadable(var, user, val, 0) > 0) { - if (user_from_cmdline) { - upsdebugx(0, "User '%s' specified in driver section " - "was ignored due to '%s' specified on command line", - val, user); - } else { - upsdebugx(1, "Overriding previously specified user '%s' " - "with '%s' specified for driver section", - user, val); - free(user); - user = xstrdup(val); + if (!strcmp(var, "user")) { + if (testval_reloadable(var, user, val, 0) > 0) { + if (user_from_cmdline) { + upsdebugx(0, "User '%s' specified in driver section " + "was ignored due to '%s' specified on command line", + val, user); + } else { + upsdebugx(1, "Overriding previously specified user '%s' " + "with '%s' specified for driver section", + user, val); + free(user); + user = xstrdup(val); + } } return 1; /* handled */ } - if (!strcmp(var, "group") && testval_reloadable(var, group, val, 0) > 0) { - if (group_from_cmdline) { - upsdebugx(0, "Group '%s' specified in driver section " - "was ignored due to '%s' specified on command line", - val, group); - } else { - upsdebugx(1, "Overriding previously specified group '%s' " - "with '%s' specified for driver section", - group, val); - free(group); - group = xstrdup(val); + if (!strcmp(var, "group")) { + if (testval_reloadable(var, group, val, 0) > 0) { + if (group_from_cmdline) { + upsdebugx(0, "Group '%s' specified in driver section " + "was ignored due to '%s' specified on command line", + val, group); + } else { + upsdebugx(1, "Overriding previously specified group '%s' " + "with '%s' specified for driver section", + group, val); + free(group); + group = xstrdup(val); + } } return 1; /* handled */ } @@ -601,7 +609,6 @@ static int main_arg(char *var, char *val) * be noticed by the reload operation currently, however. */ if (!strcmp(var, "pollinterval")) { - int do_handle = 1; char buf[SMALLBUF]; /* log a message if value changed; skip if no good buf */ @@ -636,16 +643,16 @@ static int main_arg(char *var, char *val) * and the other to take hold. Both disappearing would not * be noticed by the reload operation currently, however. */ - if (!strcmp(var, "synchronous") - && testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0 - ) { - if (!strcmp(val, "yes")) - do_synchronous=1; - else - if (!strcmp(val, "auto")) - do_synchronous=-1; - else - do_synchronous=0; + if (!strcmp(var, "synchronous")) { + if (testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0) { + if (!strcmp(val, "yes")) + do_synchronous=1; + else + if (!strcmp(val, "auto")) + do_synchronous=-1; + else + do_synchronous=0; + } return 1; /* handled */ } @@ -660,7 +667,10 @@ static int main_arg(char *var, char *val) /* Allow each driver to specify its minimal debugging level - * admins can set more with command-line args, but can't set - * less without changing config. Should help debug of services. */ + * less without changing config. Should help debug of services. + * Note: during reload_flag==1 handling this is reset to -1, to + * catch commented-away settings, so not checking previous value. + */ if (!strcmp(var, "debug_min")) { int lvl = -1; // typeof common/common.c: int nut_debug_level if ( str_to_int (val, &lvl, 10) && lvl >= 0 ) { @@ -677,6 +687,7 @@ static int main_arg(char *var, char *val) static void do_global_args(const char *var, const char *val) { char buf[SMALLBUF]; + int do_handle = 1; upsdebugx(3, "%s: var='%s' val='%s'", __func__, @@ -685,8 +696,6 @@ static void do_global_args(const char *var, const char *val) /* Allow to reload this, why not */ if (!strcmp(var, "pollinterval")) { - int do_handle = 1; - /* log a message if value changed; skip if no good buf */ if (snprintf(buf, sizeof(buf), "%" PRIdMAX, (intmax_t)poll_interval)) { if ((do_handle = testval_reloadable(var, buf, val, 1)) == 0) { @@ -714,37 +723,49 @@ static void do_global_args(const char *var, const char *val) * warning if it did change (so driver restart is needed to apply) */ - if (!strcmp(var, "chroot") && testval_reloadable(var, chroot_path, val, 0) > 0) { - free(chroot_path); - chroot_path = xstrdup(val); + if (!strcmp(var, "chroot")) { + if (testval_reloadable(var, chroot_path, val, 0) > 0) { + free(chroot_path); + chroot_path = xstrdup(val); + } + + return; } - if (!strcmp(var, "user") && testval_reloadable(var, user, val, 0) > 0) { - if (user_from_cmdline) { - upsdebugx(0, "User specified in global section '%s' " - "was ignored due to '%s' specified on command line", - val, user); - } else { - upsdebugx(1, "Overriding previously specified user '%s' " - "with '%s' specified in global section", - user, val); - free(user); - user = xstrdup(val); + if (!strcmp(var, "user")) { + if (testval_reloadable(var, user, val, 0) > 0) { + if (user_from_cmdline) { + upsdebugx(0, "User specified in global section '%s' " + "was ignored due to '%s' specified on command line", + val, user); + } else { + upsdebugx(1, "Overriding previously specified user '%s' " + "with '%s' specified in global section", + user, val); + free(user); + user = xstrdup(val); + } } + + return; } - if (!strcmp(var, "group") && testval_reloadable(var, group, val, 0) > 0) { - if (group_from_cmdline) { - upsdebugx(0, "Group specified in global section '%s' " - "was ignored due to '%s' specified on command line", - val, group); - } else { - upsdebugx(1, "Overriding previously specified group '%s' " - "with '%s' specified in global section", - group, val); - free(group); - group = xstrdup(val); + if (!strcmp(var, "group")) { + if (testval_reloadable(var, group, val, 0) > 0) { + if (group_from_cmdline) { + upsdebugx(0, "Group specified in global section '%s' " + "was ignored due to '%s' specified on command line", + val, group); + } else { + upsdebugx(1, "Overriding previously specified group '%s' " + "with '%s' specified in global section", + group, val); + free(group); + group = xstrdup(val); + } } + + return; } /* Allow to reload this, why not @@ -755,21 +776,26 @@ static void do_global_args(const char *var, const char *val) * and the other to take hold. Both disappearing would not * be noticed by the reload operation currently, however. */ - if (!strcmp(var, "synchronous") - && testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0 - ) { - if (!strcmp(val, "yes")) - do_synchronous=1; - else - if (!strcmp(val, "auto")) - do_synchronous=-1; - else - do_synchronous=0; + if (!strcmp(var, "synchronous")) { + if (testval_reloadable(var, ((do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto")), val, 1) > 0) { + if (!strcmp(val, "yes")) + do_synchronous=1; + else + if (!strcmp(val, "auto")) + do_synchronous=-1; + else + do_synchronous=0; + } + + return; } /* Allow to specify its minimal debugging level for all drivers - * admins can set more with command-line args, but can't set - * less without changing config. Should help debug of services. */ + * less without changing config. Should help debug of services. + * Note: during reload_flag==1 handling this is reset to -1, to + * catch commented-away settings, so not checking previous value. + */ if (!strcmp(var, "debug_min")) { int lvl = -1; // typeof common/common.c: int nut_debug_level if ( str_to_int (val, &lvl, 10) && lvl >= 0 ) { @@ -777,6 +803,8 @@ static void do_global_args(const char *var, const char *val) } else { upslogx(LOG_INFO, "WARNING : Invalid debug_min value found in ups.conf global settings"); } + + return; } /* unrecognized */ From b895bc657bb6dc7ca863ce46d4a3d97f4c99d0e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 18:24:35 +0200 Subject: [PATCH 0632/1232] drivers/main.c: assign_debug_level(): update messages and comments, report if nut_debug_level_args overrides smaller/unset nut_debug_level_upsconf --- drivers/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index cc0484ad24..d1989f97aa 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -920,12 +920,13 @@ static void assign_debug_level(void) { int nut_debug_level_upsconf = -1; if (nut_debug_level_global >= 0 && nut_debug_level_driver >= 0) { + /* Use nearest-defined fit */ nut_debug_level_upsconf = nut_debug_level_driver; if (reload_flag) { upslogx(LOG_INFO, "Applying debug_min=%d from ups.conf" - " driver section (overriding global)", - nut_debug_level_upsconf); + " driver section (overriding global %d)", + nut_debug_level_upsconf, nut_debug_level_global); } } else { if (nut_debug_level_global >= 0) { @@ -944,8 +945,9 @@ static void assign_debug_level(void) { } } - if (reload_flag && nut_debug_level_upsconf == -1) { - /* DEBUG_MIN is absent or commented-away in ups.conf */ + if (reload_flag && nut_debug_level_upsconf <= nut_debug_level_args) { + /* DEBUG_MIN is absent or commented-away in ups.conf, + * or is smaller than te CLI arg '-D' count */ upslogx(LOG_INFO, "Applying debug level %d from " "original command line arguments", From a81b16179f9a1fc19cd83234d6e40de07cb87184 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 18:38:15 +0200 Subject: [PATCH 0633/1232] scripts/systemd/nut-driver@.service.in: support ExecReload via "kill -SIGHUP" [#1903] --- scripts/systemd/nut-driver@.service.in | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 5139a28d47..449408dd47 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -45,6 +45,7 @@ EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' +ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl stop "$NUTDEV"' # Restart really always, do not stop trying: StartLimitInterval=0 From 16a270a9afe6fa94041d2eabb991e3ad03299b91 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 18:38:32 +0200 Subject: [PATCH 0634/1232] scripts/systemd/nut-driver@.service.in: typo fix in comment --- scripts/systemd/nut-driver@.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 449408dd47..439d083c33 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -51,7 +51,7 @@ ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-de StartLimitInterval=0 Restart=always # Protract the "hold-off" interval, so if the device connection is -# lost, the driver does not reapidly restart and fail too many times, +# lost, the driver does not rapidly restart and fail too many times, # and then systemd would keep the unit failed without further retries. # Notably, this helps start "dummy-ups" drivers retranslating local # devices (so getting a chicken-and-egg problem for driver-upsd-driver From f3b79ff0f7a6ecc04a380ec0947033b78b704fed Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 19:48:13 +0200 Subject: [PATCH 0635/1232] common/common.c: upsnotify(): support posting MONOTONIC_USEC when RELOADING/READY [#1903] --- common/common.c | 92 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/common/common.c b/common/common.c index d3b0937b94..8c2166c09a 100644 --- a/common/common.c +++ b/common/common.c @@ -19,6 +19,7 @@ */ #include "common.h" +#include "timehead.h" #include #ifndef WIN32 @@ -658,6 +659,52 @@ const char *xbasename(const char *file) return p + 1; } +#if HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC +/* From https://github.com/systemd/systemd/blob/main/src/basic/time-util.c + * and https://github.com/systemd/systemd/blob/main/src/basic/time-util.h + */ +typedef uint64_t usec_t; +typedef uint64_t nsec_t; +#define PRI_NSEC PRIu64 +#define PRI_USEC PRIu64 + +#define USEC_INFINITY ((usec_t) UINT64_MAX) +#define NSEC_INFINITY ((nsec_t) UINT64_MAX) + +#define MSEC_PER_SEC 1000ULL +#define USEC_PER_SEC ((usec_t) 1000000ULL) +#define USEC_PER_MSEC ((usec_t) 1000ULL) +#define NSEC_PER_SEC ((nsec_t) 1000000000ULL) +#define NSEC_PER_MSEC ((nsec_t) 1000000ULL) +#define NSEC_PER_USEC ((nsec_t) 1000ULL) + +static usec_t timespec_load(const struct timespec *ts) { + assert(ts); + + if (ts->tv_sec < 0 || ts->tv_nsec < 0) + return USEC_INFINITY; + + if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) + return USEC_INFINITY; + + return + (usec_t) ts->tv_sec * USEC_PER_SEC + + (usec_t) ts->tv_nsec / NSEC_PER_USEC; +} + +static nsec_t timespec_load_nsec(const struct timespec *ts) { + assert(ts); + + if (ts->tv_sec < 0 || ts->tv_nsec < 0) + return NSEC_INFINITY; + + if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC) + return NSEC_INFINITY; + + return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; +} +#endif + /* Send (daemon) state-change notifications to an * external service management framework such as systemd */ @@ -669,6 +716,15 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) char msgbuf[LARGEBUF]; size_t msglen = 0; +#if HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC + /* In current systemd, this is only used for RELOADING/READY after + * a reload action for Type=notify-reload; for more details see + * https://github.com/systemd/systemd/blob/main/src/core/service.c#L2618 + */ + struct timespec monoclock_ts; + int got_monoclock = clock_gettime(CLOCK_MONOTONIC, &monoclock_ts); +#endif + /* Prepare the message (if any) as a string */ msgbuf[0] = '\0'; if (fmt) { @@ -719,6 +775,22 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) upsnotify_reported_disabled_systemd = 1; } else { # ifdef HAVE_SD_NOTIFY + char monoclock_str[SMALLBUF]; + monoclock_str[0] = '\0'; +#if HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC + if (got_monoclock == 0) { + usec_t monots = timespec_load(&monoclock_ts); + ret = snprintf(monoclock_str + 1, sizeof(monoclock_str) - 1, "MONOTONIC_USEC=%" PRI_USEC, monots); + if ((ret < 0) || (ret >= (int) sizeof(monoclock_str) - 1)) { + syslog(LOG_WARNING, + "%s (%s:%d): snprintf needed more than %" PRIuSIZE " bytes: %d", + __func__, __FILE__, __LINE__, sizeof(monoclock_str), ret); + msglen = 0; + } else { + monoclock_str[0] = '\n'; + } + } +#endif # if ! DEBUG_SYSTEMD_WATCHDOG if (state != NOTIFY_STATE_WATCHDOG || !upsnotify_reported_watchdog_systemd) @@ -741,8 +813,9 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) switch (state) { case NOTIFY_STATE_READY: ret = snprintf(buf + msglen, sizeof(buf) - msglen, - "%sREADY=1", - msglen ? "\n" : ""); + "%sREADY=1%s", + msglen ? "\n" : "", + monoclock_str); break; case NOTIFY_STATE_READY_WITH_PID: @@ -751,9 +824,10 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) if (snprintf(pidbuf, sizeof(pidbuf), "%lu", (unsigned long) getpid())) { ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%sREADY=1\n" - "MAINPID=%s", + "MAINPID=%s%s", msglen ? "\n" : "", - pidbuf); + pidbuf, + monoclock_str); upsdebugx(6, "%s: notifying systemd about MAINPID=%s", __func__, pidbuf); /* https://github.com/systemd/systemd/issues/25961 @@ -768,8 +842,9 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) "plain NOTIFY_STATE_READY", __func__); ret = snprintf(buf + msglen, sizeof(buf) - msglen, - "%sREADY=1", - msglen ? "\n" : ""); + "%sREADY=1%s", + msglen ? "\n" : "", + monoclock_str); /* TODO: Maybe revise/drop this tweak if * loggers other than systemd are used: */ state = NOTIFY_STATE_READY; @@ -778,9 +853,10 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) break; case NOTIFY_STATE_RELOADING: - ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%s%s", + ret = snprintf(buf + msglen, sizeof(buf) - msglen, "%s%s%s", msglen ? "\n" : "", - "RELOADING=1"); + "RELOADING=1", + monoclock_str); break; case NOTIFY_STATE_STOPPING: From 2f1f9e62fc1bcd75747345cb5af53e46410a7415 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 19:49:05 +0200 Subject: [PATCH 0636/1232] configure.ac: for common.c::upsnotify(): detect support for HAVE_CLOCK_GETTIME and HAVE_CLOCK_MONOTONIC [#1903] --- configure.ac | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c570e17496..95270dbc40 100644 --- a/configure.ac +++ b/configure.ac @@ -839,11 +839,40 @@ if (p == NULL || *p != '\0') return 1])], [ac_cv_func_strptime=yes], [ac_cv_func_strptime=no] )]) AS_IF([test x"${ac_cv_func_strptime}" = xyes], - [AC_DEFINE([HAVE_STRPTIME], 1, [defined if standard library has, and C standard allows, the strptime(s1,s2) method])], + [AC_DEFINE([HAVE_STRPTIME], 1, [defined if standard library has, and C standard allows, the strptime(s1,s2,tm) method])], [AC_MSG_WARN([Optional C library routine strptime not found; a fallback implementation will be built in])] ) AM_CONDITIONAL([HAVE_STRPTIME], [test x"${ac_cv_func_strptime}" = "xyes"]) +AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC,ts)], + [ac_cv_func_clock_gettime], + [AX_RUN_OR_LINK_IFELSE( + [AC_LANG_PROGRAM([$CODE_STRINGINCL +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +], + [struct timespec monoclock_ts; +int got_monoclock = clock_gettime(CLOCK_MONOTONIC, &monoclock_ts); +if (ts.tv_sec < 0 || ts.tv_nsec < 0) return 1])], + [ac_cv_func_clock_gettime=yes], [ac_cv_func_clock_gettime=no] + )]) +AS_IF([test x"${ac_cv_func_clock_gettime}" = xyes], + [AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [defined if standard library has, and C standard allows, the clock_gettime(clkid,ts) method]) + AC_DEFINE([HAVE_CLOCK_MONOTONIC], 1, [defined if standard library has, and C standard allows, the CLOCK_MONOTONIC macro or token])], + [AC_MSG_WARN([Optional C library routine clock_gettime not found; will not be used in notifications])] + ) +dnl Currently these two are the same for us: +AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test x"${ac_cv_func_clock_gettime}" = "xyes"]) +AM_CONDITIONAL([HAVE_CLOCK_MONOTONIC], [test x"${ac_cv_func_clock_gettime}" = "xyes"]) + AC_CACHE_CHECK([for strnlen(s1,s2,tm)], [ac_cv_func_strnlen], [AX_RUN_OR_LINK_IFELSE( From 58bed0303a496de0219eedb3eb797f04afcc2634 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 19:50:02 +0200 Subject: [PATCH 0637/1232] configure.ac: for common.c::upsnotify(): detect support for systemd Type=notify-reload and enable it for nut-driver@.service if applicable [#1903] --- configure.ac | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/configure.ac b/configure.ac index 95270dbc40..8e78ff7f08 100644 --- a/configure.ac +++ b/configure.ac @@ -3216,6 +3216,27 @@ AS_CASE(["${nut_with_libsystemd}"], ]) AC_MSG_RESULT(${with_libsystemd}) +AC_PATH_PROG([SYSTEMD_ANALYZE_PROGRAM], [systemd-analyze], [/usr/bin/systemd-analyze]) + +dnl Relevant since 2023: https://github.com/systemd/systemd/pull/25916 +SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD=no +AS_IF([test -x "$SYSTEMD_ANALYZE_PROGRAM"], [ + AC_MSG_CHECKING([if your systemd version supports Type=notify-reload]) + myFILE="`mktemp systemd-analyze-XXXXXX.service`" + cat > "$myFILE" << EOF +[Unit] +Description=temp +[Service] +ExecStart=/bin/true +Type=notify-reload +EOF + if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" ; then + SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD=yes + fi + rm -f "$myFILE" + AC_MSG_RESULT([${SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD}]) + ]) + AS_IF([test x"${with_libsystemd}" = xyes], [ dnl Built with sd_notify support dnl Note: `upsd -FF` both runs without forking and leaves a PID file, as @@ -3226,6 +3247,9 @@ AS_IF([test x"${with_libsystemd}" = xyes], [ SYSTEMD_DAEMON_TYPE_UPSMON="notify" SYSTEMD_DAEMON_ARGS_DRIVER="" SYSTEMD_DAEMON_TYPE_DRIVER="notify" + AS_IF([test x"${SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD}" = xyes], [ + AM_COND_IF([HAVE_CLOCK_GETTIME], [AM_COND_IF([HAVE_CLOCK_MONOTONIC], [SYSTEMD_DAEMON_TYPE_DRIVER="notify-reload"])]) + ]) dnl Calling shell, upsdrvctl, driver, and then it forks... ugh! dnl https://github.com/systemd/systemd/issues/25961 dnl FIXME: if NotifyAccess=cgroup appears, use it (consult SYSTEMD_VERSION) From 1c04085913e65a051fafe551f42c375460ae8603 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 19:53:58 +0200 Subject: [PATCH 0638/1232] configure.ac: for common.c::upsnotify(): detect actual support for systemd Type=notify for good measure [#1903, #1590] --- configure.ac | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8e78ff7f08..fa4023c372 100644 --- a/configure.ac +++ b/configure.ac @@ -3219,6 +3219,24 @@ AC_MSG_RESULT(${with_libsystemd}) AC_PATH_PROG([SYSTEMD_ANALYZE_PROGRAM], [systemd-analyze], [/usr/bin/systemd-analyze]) dnl Relevant since 2023: https://github.com/systemd/systemd/pull/25916 +SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY=no +AS_IF([test -x "$SYSTEMD_ANALYZE_PROGRAM"], [ + AC_MSG_CHECKING([if your systemd version supports Type=notify]) + myFILE="`mktemp systemd-analyze-XXXXXX.service`" + cat > "$myFILE" << EOF +[Unit] +Description=temp +[Service] +ExecStart=/bin/true +Type=notify +EOF + if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" ; then + SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY=yes + fi + rm -f "$myFILE" + AC_MSG_RESULT([${SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY}]) + ]) + SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD=no AS_IF([test -x "$SYSTEMD_ANALYZE_PROGRAM"], [ AC_MSG_CHECKING([if your systemd version supports Type=notify-reload]) @@ -3237,7 +3255,7 @@ EOF AC_MSG_RESULT([${SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD}]) ]) -AS_IF([test x"${with_libsystemd}" = xyes], [ +AS_IF([test x"${with_libsystemd}" = xyes && test x"${SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY}" = xyes], [ dnl Built with sd_notify support dnl Note: `upsd -FF` both runs without forking and leaves a PID file, as dnl needed for `upsd -c reload` in legacy scripts and old habits to work: From c65d8c28c6a8d66208e6d71a0f4cef6af58df0e2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 20:05:36 +0200 Subject: [PATCH 0639/1232] configure.ac: fix "end-user" square brackets for M4 markup [#1903] --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index fa4023c372..3ef4a508df 100644 --- a/configure.ac +++ b/configure.ac @@ -3224,9 +3224,9 @@ AS_IF([test -x "$SYSTEMD_ANALYZE_PROGRAM"], [ AC_MSG_CHECKING([if your systemd version supports Type=notify]) myFILE="`mktemp systemd-analyze-XXXXXX.service`" cat > "$myFILE" << EOF -[Unit] +@<:@Unit@:>@ Description=temp -[Service] +@<:@Service@:>@ ExecStart=/bin/true Type=notify EOF @@ -3242,9 +3242,9 @@ AS_IF([test -x "$SYSTEMD_ANALYZE_PROGRAM"], [ AC_MSG_CHECKING([if your systemd version supports Type=notify-reload]) myFILE="`mktemp systemd-analyze-XXXXXX.service`" cat > "$myFILE" << EOF -[Unit] +@<:@Unit@:>@ Description=temp -[Service] +@<:@Service@:>@ ExecStart=/bin/true Type=notify-reload EOF From c67c59c76b79328e31818d177551a543bfca6644 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 20:09:42 +0200 Subject: [PATCH 0640/1232] configure.ac: do not make noise with SYSTEMD_ANALYZE_PROGRAM [#1903, #1590] --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 3ef4a508df..72eeadce15 100644 --- a/configure.ac +++ b/configure.ac @@ -3230,7 +3230,7 @@ Description=temp ExecStart=/bin/true Type=notify EOF - if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" ; then + if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>/dev/null >/dev/null ; then SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY=yes fi rm -f "$myFILE" @@ -3248,7 +3248,7 @@ Description=temp ExecStart=/bin/true Type=notify-reload EOF - if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" ; then + if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>/dev/null >/dev/null ; then SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD=yes fi rm -f "$myFILE" From 1a04fafd6c0db1946bcc1a334426f8c0647c831a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 20:19:28 +0200 Subject: [PATCH 0641/1232] configure.ac: do fail checks due to unknown tokens with SYSTEMD_ANALYZE_PROGRAM [#1903, #1590] --- configure.ac | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 72eeadce15..7e41bc82e2 100644 --- a/configure.ac +++ b/configure.ac @@ -3230,7 +3230,9 @@ Description=temp ExecStart=/bin/true Type=notify EOF - if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>/dev/null >/dev/null ; then + if myOUT="`"$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>&1`" \ + && ! (echo "$myOUT" | grep "Failed to parse service type, ignoring") \ + ; then SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY=yes fi rm -f "$myFILE" @@ -3248,7 +3250,9 @@ Description=temp ExecStart=/bin/true Type=notify-reload EOF - if "$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>/dev/null >/dev/null ; then + if myOUT="`"$SYSTEMD_ANALYZE_PROGRAM" verify "$myFILE" 2>&1`" \ + && ! (echo "$myOUT" | grep "Failed to parse service type, ignoring") \ + ; then SYSTEMD_SUPPORTS_DAEMON_TYPE_NOTIFY_RELOAD=yes fi rm -f "$myFILE" From c2ed050d4a4871d4ff862ace1784ac2b87950aee Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 20:44:31 +0200 Subject: [PATCH 0642/1232] NEWS: Implemented basic support for `ups.conf` reloading in NUT drivers [#1903] --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index d5f56cf269..c841cdaa22 100644 --- a/NEWS +++ b/NEWS @@ -272,6 +272,12 @@ https://github.com/networkupstools/nut/milestone/8 `nut-server.service` as `upsd.service`, and `nut-monitor.service` as `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Implemented basic support for `ups.conf` reloading in NUT drivers, + currently limited to `SIGHUP` handling and with a goal of changing + `debug_min` setting for a running driver. As currently implemented, + would not fully benefit the drivers on systems managed by real-time + `nut-driver-enumerator` (it needs to be taught to play well) [#1903] + - Recipes and `main.c` code were enhanced to produce a `libdummy_mockdrv.la` helper library during build (not intended to be installed nor distributed), in order to facilitate creation of test programs which behave like a driver From 3ddfc52b7af283be4dc0152f9867b83e9f76bbde Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 17 Apr 2023 20:52:21 +0200 Subject: [PATCH 0643/1232] scripts/Solaris/nut-driver.xml.in: define basic SMF "refresh" support to send SIGHUP to a driver [#1903] --- scripts/Solaris/nut-driver.xml.in | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/Solaris/nut-driver.xml.in b/scripts/Solaris/nut-driver.xml.in index b8334f2d12..752c8a770d 100644 --- a/scripts/Solaris/nut-driver.xml.in +++ b/scripts/Solaris/nut-driver.xml.in @@ -2,14 +2,14 @@ - + + + From ae1d7593f182a2407de85d4b01c2dc2d517eada4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 20:54:42 +0200 Subject: [PATCH 0691/1232] scripts/systemd/nut-driver@.service.in: exec upsdrvctl to avoid another extra fork --- scripts/systemd/nut-driver@.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index 3990a01cdd..b75e86a65e 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -44,7 +44,7 @@ Environment=NUT_IGNORE_NOWAIT=true EnvironmentFile=-@CONFPATH@/nut.conf SyslogIdentifier=%N ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf -ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' +ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; exec @SBINDIR@/upsdrvctl @SYSTEMD_DAEMON_ARGS_DRIVER@ start "$NUTDEV"' # SIGHUP: simple reload (ignore values we can not change on the fly) # SIGUSR1: reload-or-exit (let systemd resuscitate the service then) ExecReload=/bin/kill -USR1 $MAINPID From 32c477c932439d86d5392bd5918f686aca55ed82 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 20:59:02 +0200 Subject: [PATCH 0692/1232] NEWS: clarify nut-driver-enumerator vs. debug_min edits [#1903] --- NEWS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c53427b41e..677ecd26c9 100644 --- a/NEWS +++ b/NEWS @@ -276,7 +276,9 @@ https://github.com/networkupstools/nut/milestone/8 currently limited to `SIGHUP` handling and with a goal of changing `debug_min` setting for a running driver. As currently implemented, would not fully benefit the drivers on systems managed by real-time - `nut-driver-enumerator` (it needs to be taught to play well), but + `nut-driver-enumerator` (it does not track what exactly changed), but + it is possible to change/add/remove `debug_min` in the global section + and the drivers get only reloaded and not restarted. Reload signals should be reasonably supported with `upsdrvctl`. Relevant CLI options for `-c CMD` handing were added to drivers and `upsdrvctl` [#1903] From 9976707bf849af37dd9ae0f634b8a7b37757030c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 21:10:30 +0200 Subject: [PATCH 0693/1232] drivers/upsdrvctl.c: fix builds for WIN32 [#1903] --- drivers/upsdrvctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 6d713364ff..4ca9861982 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1237,12 +1237,12 @@ int main(int argc, char **argv) /* raise exit_flag upon SIGTERM, Ctrl+C, etc. */ setup_signals(); while (!exit_flag) { + ups_t *tmp = upstable, *next; #ifndef WIN32 /* Track if any child process has stopped (due to * an error, normal exit, signal...) to kill others * and exit the tool - with error if applicable. */ - ups_t *tmp = upstable, *next; while (tmp) { next = tmp->next; if (tmp->pid != -1) { From f15cfd95a497c00d9b7ea53e448a9d470e1f7244 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 21:30:24 +0200 Subject: [PATCH 0694/1232] drivers/upsdrvctl.c: set_signal_flag(): relax const-ness to save the signal --- drivers/upsdrvctl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 4ca9861982..255f29d253 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -420,7 +420,14 @@ static void set_signal_flag(const #endif sig ) { - signal_flag = sig; + /* non-const, so some casting trickery */ + signal_flag = ( +#ifndef WIN32 + int +#else + char * +#endif + )sig; } static void reset_signal_flag(void) From d372e772bd6e8c31297d29f9de78b59aa7f80e0b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 21:31:59 +0200 Subject: [PATCH 0695/1232] drivers/upsdrvctl.c: fix main loop buildability for WIN32 [#1903] --- drivers/upsdrvctl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 255f29d253..f8ba439a6c 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1244,8 +1244,8 @@ int main(int argc, char **argv) /* raise exit_flag upon SIGTERM, Ctrl+C, etc. */ setup_signals(); while (!exit_flag) { - ups_t *tmp = upstable, *next; #ifndef WIN32 + ups_t *tmp = upstable, *next; /* Track if any child process has stopped (due to * an error, normal exit, signal...) to kill others * and exit the tool - with error if applicable. @@ -1264,9 +1264,9 @@ int main(int argc, char **argv) elapsed = difftime(now, last_dangerous_reload); if (elapsed < 60 || (es - 128) == SIGCMD_RELOAD_OR_EXIT -#ifdef SIGCMD_RELOAD_OR_RESTART +# ifdef SIGCMD_RELOAD_OR_RESTART || (es - 128) == SIGCMD_RELOAD_OR_RESTART -#endif +# endif ) { /* Arbitrary but generous time to handle * a reload including driver loop lag */ @@ -1302,14 +1302,13 @@ int main(int argc, char **argv) /* NOTE: Users really should run one driver per instance, * wrapped in services where available */ } -#endif /* WIN32 */ if (signal_flag) { upsdebugx(1, "upsdrvctl: handling signal: starting"); if (signal_flag == SIGCMD_RELOAD_OR_EXIT -#ifdef SIGCMD_RELOAD_OR_RESTART +# ifdef SIGCMD_RELOAD_OR_RESTART || signal_flag == SIGCMD_RELOAD_OR_RESTART -#endif +# endif ) time(&last_dangerous_reload); tmp = upstable; @@ -1321,6 +1320,7 @@ int main(int argc, char **argv) reset_signal_flag(); upsdebugx(1, "upsdrvctl: handling signal: finished"); } +#endif /* WIN32 */ sleep(1); } From 989ca841c4367a14ff0ce75fb838d0979d8f448d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 19 Apr 2023 21:34:09 +0200 Subject: [PATCH 0696/1232] drivers/upsdrvctl.c: buildability for WIN32 (unused code warnings) [#1903] --- drivers/upsdrvctl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index f8ba439a6c..2abc6209ca 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -83,8 +83,10 @@ static void (*command)(const ups_t *) = NULL; /* signal handling */ int exit_flag = 0; +#ifndef WIN32 static int reload_flag = 0; static time_t last_dangerous_reload = 0; +#endif #ifndef WIN32 static int signal_flag = 0; #else @@ -174,6 +176,8 @@ void do_upsconf_args(char *arg_upsname, char *var, char *val) upstable = tmp; } +#ifndef WIN32 +/* TODO: implement WIN32 */ /* handle generally signalling the UPS */ static void signal_driver_cmd(const ups_t *ups, #ifndef WIN32 @@ -257,6 +261,7 @@ static void signal_driver_cmd(const ups_t *ups, static void signal_driver(const ups_t *ups) { signal_driver_cmd(ups, signal_flag); } +#endif /* WIN32 */ /* handle sending the signal */ static void stop_driver(const ups_t *ups) @@ -439,6 +444,9 @@ static void reset_signal_flag(void) #endif } +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ + static void set_reload_flag(const #ifndef WIN32 int @@ -474,6 +482,7 @@ static void set_reload_flag(const __func__, sig, strsignal(sig), reload_flag); #endif } +#endif static void setup_signals(void) { From 963bc5952039f54a9d47cde245de8e1b86aeb80e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 00:33:58 +0200 Subject: [PATCH 0697/1232] tests/NIT/nit.sh: report test case names at start of ther methods, to find error reports in log more easily --- tests/NIT/nit.sh | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0470e6c6d8..8b746f7af7 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -545,7 +545,7 @@ PASSED=0 testcase_upsd_no_configs_at_all() { log_separator - log_info "Test UPSD without configs at all" + log_info "[testcase_upsd_no_configs_at_all] Test UPSD without configs at all" upsd -F if [ "$?" = 0 ]; then log_error "upsd should fail without configs" @@ -559,7 +559,7 @@ testcase_upsd_no_configs_at_all() { testcase_upsd_no_configs_driver_file() { log_separator - log_info "Test UPSD without driver config file" + log_info "[testcase_upsd_no_configs_driver_file] Test UPSD without driver config file" generatecfg_upsd_trivial upsd -F if [ "$?" = 0 ]; then @@ -574,7 +574,7 @@ testcase_upsd_no_configs_driver_file() { testcase_upsd_no_configs_in_driver_file() { log_separator - log_info "Test UPSD without drivers defined in config file" + log_info "[testcase_upsd_no_configs_in_driver_file] Test UPSD without drivers defined in config file" generatecfg_upsd_trivial generatecfg_ups_trivial upsd -F @@ -590,7 +590,7 @@ testcase_upsd_no_configs_in_driver_file() { testcase_upsd_allow_no_device() { log_separator - log_info "Test UPSD allowed to run without driver configs" + log_info "[testcase_upsd_allow_no_device] Test UPSD allowed to run without driver configs" generatecfg_upsd_nodev generatecfg_upsdusers_trivial generatecfg_ups_trivial @@ -745,7 +745,7 @@ sandbox_start_drivers() { testcase_sandbox_start_upsd_alone() { log_separator - log_info "Test starting UPSD but not a driver before it" + log_info "[testcase_sandbox_start_upsd_alone] Test starting UPSD but not a driver before it" sandbox_start_upsd EXPECTED_UPSLIST='dummy' @@ -789,6 +789,7 @@ UPS2" testcase_sandbox_start_upsd_after_drivers() { # Historically this is a fallback from testcase_sandbox_start_drivers_after_upsd + log_info "[testcase_sandbox_start_upsd_after_drivers] Test starting UPSD after drivers" kill -15 $PID_UPSD 2>/dev/null wait $PID_UPSD @@ -828,7 +829,7 @@ testcase_sandbox_start_drivers_after_upsd() { testcase_sandbox_start_upsd_alone sandbox_start_drivers - log_info "Query driver state from UPSD by UPSC after driver startup" + log_info "[testcase_sandbox_start_drivers_after_upsd] Query driver state from UPSD by UPSC after driver startup" COUNTDOWN=60 while [ "$COUNTDOWN" -gt 0 ]; do # For query errors or known wait, keep looping @@ -875,6 +876,7 @@ testcase_sandbox_start_drivers_after_upsd() { } testcase_sandbox_upsc_query_model() { + loginfo "[testcase_sandbox_upsc_query_model] Query model from dummy device" runcmd upsc dummy@localhost:$NUT_PORT device.model || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" if [ x"$CMDOUT" != x"Dummy UPS" ] ; then log_error "got this reply for upsc query when 'Dummy UPS' was expected: $CMDOUT" @@ -886,7 +888,7 @@ testcase_sandbox_upsc_query_model() { } testcase_sandbox_upsc_query_bogus() { - log_info "Query driver state from UPSD by UPSC for bogus info" + log_info "[testcase_sandbox_upsc_query_bogus] Query driver state from UPSD by UPSC for bogus info" runcmd upsc dummy@localhost:$NUT_PORT ups.bogus.value && { log_error "upsc was supposed to answer with error exit code: $CMDOUT" FAILED="`expr $FAILED + 1`" @@ -904,7 +906,7 @@ testcase_sandbox_upsc_query_bogus() { testcase_sandbox_upsc_query_timer() { log_separator - log_info "Test that dummy-ups TIMER action changes the reported state" + log_info "[testcase_sandbox_upsc_query_timer] Test that dummy-ups TIMER action changes the reported state" # Driver is set up to flip ups.status every 5 sec, so check every 3 # TODO: Any need to convert to runcmd()? OUT1="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond on port ${NUT_PORT} ($?): $OUT1" ; sleep 3 @@ -946,7 +948,7 @@ isTestablePython() { testcase_sandbox_python_without_credentials() { isTestablePython || return 0 log_separator - log_info "Call Python module test suite: PyNUT (NUT Python bindings) without login credentials" + log_info "[testcase_sandbox_python_without_credentials] Call Python module test suite: PyNUT (NUT Python bindings) without login credentials" if ( unset NUT_USER || true unset NUT_PASS || true "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" @@ -967,7 +969,7 @@ testcase_sandbox_python_with_credentials() { # but the dummy data does not currently let issue the commands and # setvars tested from python script. log_separator - log_info "Call Python module test suite: PyNUT (NUT Python bindings) with login credentials" + log_info "[testcase_sandbox_python_with_credentials] Call Python module test suite: PyNUT (NUT Python bindings) with login credentials" if ( NUT_USER='admin' NUT_PASS="${TESTPASS_ADMIN}" @@ -987,7 +989,7 @@ testcase_sandbox_python_with_upsmon_credentials() { isTestablePython || return 0 log_separator - log_info "Call Python module test suite: PyNUT (NUT Python bindings) with upsmon role login credentials" + log_info "[testcase_sandbox_python_with_upsmon_credentials] Call Python module test suite: PyNUT (NUT Python bindings) with upsmon role login credentials" if ( NUT_USER='dummy-admin' NUT_PASS="${TESTPASS_UPSMON_PRIMARY}" @@ -1027,7 +1029,7 @@ testcase_sandbox_cppnit_without_creds() { isTestableCppNIT || return 0 log_separator - log_info "Call libnutclient test suite: cppnit without login credentials" + log_info "[testcase_sandbox_cppnit_without_creds] Call libnutclient test suite: cppnit without login credentials" if ( unset NUT_USER || true unset NUT_PASS || true "${TOP_BUILDDIR}/tests/cppnit" @@ -1045,7 +1047,7 @@ testcase_sandbox_cppnit_simple_admin() { isTestableCppNIT || return 0 log_separator - log_info "Call libnutclient test suite: cppnit with login credentials: simple admin" + log_info "[testcase_sandbox_cppnit_simple_admin] Call libnutclient test suite: cppnit with login credentials: simple admin" if ( NUT_USER='admin' NUT_PASS="${TESTPASS_ADMIN}" @@ -1073,7 +1075,7 @@ testcase_sandbox_cppnit_upsmon_primary() { isTestableCppNIT || return 0 log_separator - log_info "Call libnutclient test suite: cppnit with login credentials: upsmon-primary" + log_info "[testcase_sandbox_cppnit_upsmon_primary] Call libnutclient test suite: cppnit with login credentials: upsmon-primary" if ( NUT_USER='dummy-admin' NUT_PASS="${TESTPASS_UPSMON_PRIMARY}" @@ -1095,7 +1097,7 @@ testcase_sandbox_cppnit_upsmon_master() { isTestableCppNIT || return 0 log_separator - log_info "Call libnutclient test suite: cppnit with login credentials: upsmon-master" + log_info "[testcase_sandbox_cppnit_upsmon_master] Call libnutclient test suite: cppnit with login credentials: upsmon-master" if ( NUT_USER='dummy-admin-m' NUT_PASS="${TESTPASS_UPSMON_PRIMARY}" @@ -1139,7 +1141,7 @@ testcase_sandbox_nutscanner_list() { isTestableNutScanner || return 0 log_separator - log_info "Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" + log_info "[testcase_sandbox_nutscanner_list] Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" log_info "Preparing LD_LIBRARY_PATH='${LD_LIBRARY_PATH_CLIENT}'" # Note: for some reason `LD_LIBRARY_PATH=... runcmd ...` loses it :\ From 37c9537a6fa1de3e3c4d923e6db72416ccbdf1e3 Mon Sep 17 00:00:00 2001 From: Clappier Eric Date: Thu, 20 Apr 2023 10:54:21 +0200 Subject: [PATCH 0698/1232] Acquisition failed with daisychain epdu G3 with sensors (#1911) * Hot fix for infinite loop during discovery daisychain epdu G3 with sensors * Change log message in guesstimate_template_count function --- drivers/snmp-ups.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 33376adb34..9ebc4816d0 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -2442,6 +2442,12 @@ static int guesstimate_template_count(snmp_info_t *su_info_p) upsdebugx(1, "%s(%s)", __func__, OID_template); + /* Test if OID is indexed: safeguard for infinite loop */ + if (strchr(OID_template, '%') == NULL) { + upsdebugx(3, "Warning: non-indexed object, discarding (OID = %s)", OID_template); + return 0; + } + /* Determine if OID index starts from 0 or 1? */ #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL #pragma GCC diagnostic push From c6968db209a92bae495f1e10adc902eb91f949bf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 11:25:20 +0200 Subject: [PATCH 0699/1232] docs/sock-protocol.txt: update with some clarifications --- docs/sock-protocol.txt | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index 32cd5bf2e7..42768ba967 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -9,6 +9,11 @@ out changes to their local storage immediately, without any sort of prompting from the server. As a result, the server must always check on any driver sockets for activity. +In terms of communications, each driver is a server on the Unix socket +(or Windows named pipe) which it creates, and the data server `upsd` is +a client which knows where to find such sockets, how they are named, +and connects to all of them to send commands and receive data updates. + Formatting ---------- @@ -23,6 +28,9 @@ together on its way to the other end. Commands used by the drivers ---------------------------- +These commands (or semantically responses to server commands in some cases) +can be sent by drivers to the data server over the socket protocol. + SETINFO ~~~~~~~ @@ -161,6 +169,10 @@ strings, as per docs/net-protocol.txt GET TRACKING. Commands sent by the server --------------------------- +The data server `upsd` (or technically any client that connects to a Unix +socket or Windows named pipe provided by each NUT driver) can send the +following commands to the driver: + PING ~~~~ @@ -175,6 +187,12 @@ If a driver does not respond with the PONG within a few seconds at the most, it should be treated as dead/unavailable. Data stored in the server must not be passed on to the clients when this happens. +NOTE: For the `upsd` data server, the MAXAGE setting in upsd.conf controls +how long since the last message from the driver it is considered stale. +At 1/3 of this time the server sends a `PING` command to the driver, so +there is some time for a `PONG` to arrive and reset the timer (any other +message would serve that goal as well). + INSTCMD ~~~~~~~ @@ -262,4 +280,4 @@ Re-establishing communications If the server loses its connection to the driver and later reconnects, it must flush any local storage and start again with DUMPALL. The driver may have changed the internal state considerably during that -time, and anything other approach could leave old elements behind. +time, and any other approach could leave old elements behind. From e2715f055ee1a3d11356befa3bf419ede3b10e3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 13:25:49 +0200 Subject: [PATCH 0700/1232] drivers/main.{c,h}, drivers/dstate.c: introduce and handle shared main_instcmd() and main_setvar() handlers [#1285, #1914] --- drivers/dstate.c | 27 +++++++++++++++++++++++++-- drivers/main.c | 20 ++++++++++++++++++++ drivers/main.h | 11 +++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index b6706458ea..0765bb1ac3 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -742,7 +742,18 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) if (cmdid) upsdebugx(3, "%s: TRACKING = %s", __func__, cmdid); - /* try the new handler first if present */ + /* try the handler shared by all drivers first */ + ret = main_instcmd(arg[1], arg[2]); + if (ret == STAT_INSTCMD_HANDLED) { + /* send back execution result */ + if (cmdid) + send_tracking(conn, cmdid, ret); + + /* The command was handled, status is a separate consideration */ + return 1; + } /* else try other handler(s) */ + + /* try the driver-provided handler if present */ if (upsh.instcmd) { ret = upsh.instcmd(cmdname, cmdparam); @@ -753,6 +764,7 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) /* The command was handled, status is a separate consideration */ return 1; } + upslogx(LOG_NOTICE, "Got INSTCMD, but driver lacks a handler"); return 1; } @@ -779,7 +791,18 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) upsdebugx(3, "%s: TRACKING = %s", __func__, setid); } - /* try the new handler first if present */ + /* try the handler shared by all drivers first */ + ret = main_setvar(arg[1], arg[2]); + if (ret == STAT_SET_HANDLED) { + /* send back execution result */ + if (setid) + send_tracking(conn, setid, ret); + + /* The command was handled, status is a separate consideration */ + return 1; + } /* else try other handler(s) */ + + /* try the driver-provided handler if present */ if (upsh.setvar) { ret = upsh.setvar(arg[1], arg[2]); diff --git a/drivers/main.c b/drivers/main.c index e064f6aaeb..9ffaa7b798 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -560,6 +560,26 @@ void addvar(int vartype, const char *name, const char *desc) do_addvar(vartype, name, desc, 0); } +/* handle instant commands common for all drivers */ +int main_instcmd(const char *cmdname, const char *extra) { + NUT_UNUSED_VARIABLE(cmdname); + NUT_UNUSED_VARIABLE(extra); + + /* By default, the driver-specific values are + * unknown to shared standard handler */ + return STAT_INSTCMD_UNKNOWN; +} + +/* handle setting variables common for all drivers */ +int main_setvar(const char *varname, const char *val) { + NUT_UNUSED_VARIABLE(varname); + NUT_UNUSED_VARIABLE(val); + + /* By default, the driver-specific values are + * unknown to shared standard handler */ + return STAT_SET_UNKNOWN; +} + /* handle -x / ups.conf config details that are for this part of the code */ static int main_arg(char *var, char *val) { diff --git a/drivers/main.h b/drivers/main.h index 39dd408858..1300bcc532 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -3,6 +3,7 @@ #include "common.h" #include "upsconf.h" +#include "upshandler.h" #include "dstate.h" #include "extstate.h" #ifdef WIN32 @@ -29,6 +30,16 @@ void set_exit_flag(int sig); /* --- details for the variable/value sharing --- */ +/* handle instant commands common for all drivers + * (returns STAT_INSTCMD_* state values per enum in upshandler.h) + */ +int main_instcmd(const char *cmdname, const char *extra); + +/* handle setting variables common for all drivers + * (returns STAT_SET_* state values per enum in upshandler.h) + */ +int main_setvar(const char *varname, const char *val); + /* main calls this driver function - it needs to call addvar */ void upsdrv_makevartable(void); From 45cb90bfff62d327555375233ee783ae026f6409 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 13:29:02 +0200 Subject: [PATCH 0701/1232] drivers/main.c: debug-trace (and so use) args to main_instcmd() and main_setvar() handlers [#1285, #1914] --- drivers/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 9ffaa7b798..27c228f9bd 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -562,21 +562,27 @@ void addvar(int vartype, const char *name, const char *desc) /* handle instant commands common for all drivers */ int main_instcmd(const char *cmdname, const char *extra) { - NUT_UNUSED_VARIABLE(cmdname); - NUT_UNUSED_VARIABLE(extra); + upsdebugx(2, "entering main_instcmd(%s, %s) for [%s]", + cmdname, extra, NUT_STRARG(upsname)); /* By default, the driver-specific values are * unknown to shared standard handler */ + upsdebugx(2, "shared %s() does not handle command %s, " + "proceeding to driver-specific handler", + __func__, cmdname); return STAT_INSTCMD_UNKNOWN; } /* handle setting variables common for all drivers */ int main_setvar(const char *varname, const char *val) { - NUT_UNUSED_VARIABLE(varname); - NUT_UNUSED_VARIABLE(val); + upsdebugx(2, "entering main_setvar(%s, %s) for [%s]", + varname, val, NUT_STRARG(upsname)); /* By default, the driver-specific values are * unknown to shared standard handler */ + upsdebugx(2, "shared %s() does not handle variable %s, " + "proceeding to driver-specific handler", + __func__, varname); return STAT_SET_UNKNOWN; } From 48f7c712546d4e24dc93074d3b2c3ba3f101e317 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 13:56:00 +0200 Subject: [PATCH 0702/1232] drivers/main.c: introduce a way to show and set "driver.debug" level via socket protocol (upsrw etc.) [#1285] Closes: #1285 --- NEWS | 15 +++++++++++++++ drivers/main.c | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index cce3b9a712..67bf538253 100644 --- a/NEWS +++ b/NEWS @@ -272,6 +272,21 @@ https://github.com/networkupstools/nut/milestone/8 `nut-server.service` as `upsd.service`, and `nut-monitor.service` as `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Implemented generic support for INSTCMD and SETVAR use-cases shared by + all drivers, and in particular to see and change active debug verbosity + using the driver-server and server-client protocol (at higher priority + than CLI or config file choices) per [#1285], e.g. +------ +# Set verbosity level 6: +:; upsrw -s driver.debug=6 UPS + +# Set verbosity level 0 to disable the noise (even if debug_min is set): +:; upsrw -s driver.debug=0 UPS1@localhost + +# Un-set the protocol override, honour CLI or config-file settings again: +:; upsrw -s driver.debug=-1 remoteUPS@1.2.3.4 +------ + - Implemented basic support for `ups.conf` reloading in NUT drivers, currently limited to `SIGHUP` handling and with a goal of changing `debug_min` setting for a running driver. As currently implemented, diff --git a/drivers/main.c b/drivers/main.c index 27c228f9bd..fecb023b63 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -97,13 +97,15 @@ static int background_flag = -1; * 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). + * have more). Finally, it can also be set over socket + * protocol, taking precedence over other inputs. */ #ifndef DRIVERS_MAIN_WITHOUT_MAIN static int nut_debug_level_args = -1; #endif static int nut_debug_level_global = -1; static int nut_debug_level_driver = -1; +static int nut_debug_level_protocol = -1; #ifndef DRIVERS_MAIN_WITHOUT_MAIN /* everything else */ @@ -111,6 +113,9 @@ static char *pidfn = NULL; static int dump_data = 0; /* Store the update_count requested */ #endif /* DRIVERS_MAIN_WITHOUT_MAIN */ +/* pre-declare some private methods used */ +static void assign_debug_level(void); + /* print the driver banner */ void upsdrv_banner (void) { @@ -578,12 +583,35 @@ int main_setvar(const char *varname, const char *val) { upsdebugx(2, "entering main_setvar(%s, %s) for [%s]", varname, val, NUT_STRARG(upsname)); + if (!strcmp(varname, "driver.debug")) { + int num; + if (str_to_int(val, &num, 10)) { + if (num < 0) { + upsdebugx(nut_debug_level > 0 ? 1 : 0, + "NOTE: Will fall back to CLI/DriverConfig/GlobalConfig debug verbosity preference now"); + num = -1; + } + if (nut_debug_level > 0 && num == 0) + upsdebugx(1, "NOTE: Will disable verbose debug now, due to socket protocol request"); + nut_debug_level_protocol = num; + assign_debug_level(); + return STAT_SET_HANDLED; + } else { + goto invalid; + } + } + /* By default, the driver-specific values are * unknown to shared standard handler */ upsdebugx(2, "shared %s() does not handle variable %s, " "proceeding to driver-specific handler", __func__, varname); return STAT_SET_UNKNOWN; + +invalid: + upsdebugx(1, "Error: UPS [%s]: invalid %s value: %s", + NUT_STRARG(upsname), varname, val); + return STAT_SET_INVALID; } /* handle -x / ups.conf config details that are for this part of the code */ @@ -1005,6 +1033,15 @@ static void assign_debug_level(void) { */ int nut_debug_level_upsconf = -1; + if (nut_debug_level_protocol >= 0) { + upslogx(LOG_INFO, + "Applying debug level %d received during run-time " + "via socket protocol, ignoring other settings", + nut_debug_level_protocol); + nut_debug_level = nut_debug_level_protocol; + goto finish; + } + if (nut_debug_level_global >= 0 && nut_debug_level_driver >= 0) { /* Use nearest-defined fit */ nut_debug_level_upsconf = nut_debug_level_driver; @@ -1047,7 +1084,10 @@ static void assign_debug_level(void) { if (nut_debug_level_upsconf > nut_debug_level) nut_debug_level = nut_debug_level_upsconf; +finish: upsdebugx(1, "debug level is '%d'", nut_debug_level); + dstate_setinfo("driver.debug", "%d", nut_debug_level); + dstate_setflags("driver.debug", ST_FLAG_RW | ST_FLAG_NUMBER); } static void handle_reload_flag(void) { From 1c1a061b8981110bff6e7217d383be9ebc30c867 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 14:33:43 +0200 Subject: [PATCH 0703/1232] drivers/main.c: add support for INSTCMD "driver.killpower" [#1917] --- NEWS | 2 ++ drivers/main.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/NEWS b/NEWS index 67bf538253..baca518b23 100644 --- a/NEWS +++ b/NEWS @@ -286,6 +286,8 @@ https://github.com/networkupstools/nut/milestone/8 # Un-set the protocol override, honour CLI or config-file settings again: :; upsrw -s driver.debug=-1 remoteUPS@1.2.3.4 ------ ++ +and a `driver.killpower` instant command [#1917] - Implemented basic support for `ups.conf` reloading in NUT drivers, currently limited to `SIGHUP` handling and with a goal of changing diff --git a/drivers/main.c b/drivers/main.c index fecb023b63..f9561c5975 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -570,6 +570,14 @@ int main_instcmd(const char *cmdname, const char *extra) { upsdebugx(2, "entering main_instcmd(%s, %s) for [%s]", cmdname, extra, NUT_STRARG(upsname)); + if (!strcmp(cmdname, "driver.killpower")) { + upslogx(LOG_WARNING, "Requesting UPS [%s] to power off, " + "as/if handled by its driver by default (may exit), " + "due to socket protocol request", NUT_STRARG(upsname)); + upsdrv_shutdown(); + return STAT_INSTCMD_HANDLED; + } + /* By default, the driver-specific values are * unknown to shared standard handler */ upsdebugx(2, "shared %s() does not handle command %s, " @@ -1792,6 +1800,8 @@ int main(int argc, char **argv) writepid(pidfn); /* PID changes when backgrounding */ } + dstate_addcmd("driver.killpower"); + dstate_setinfo("driver.state", "quiet"); if (dump_data) { upsdebugx(1, "Driver initialization completed, beginning data dump (%d loops)", dump_data); From 9b3386b2ecf8006bef374836029267f4f423f79b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:01:41 +0200 Subject: [PATCH 0704/1232] drivers/dstate.c: if main_setvar()/main_instcmd() return STAT_*_INVALID, do not proceed to driver handler [#1914] --- drivers/dstate.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dstate.c b/drivers/dstate.c index 0765bb1ac3..326ce7fd78 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -751,6 +751,10 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) /* The command was handled, status is a separate consideration */ return 1; + } else if (ret == STAT_INSTCMD_INVALID) { + /* The command was acknowledged by shared handler, but not + * valid in current circumstances - do not pass to driver */ + return 1; } /* else try other handler(s) */ /* try the driver-provided handler if present */ @@ -800,6 +804,10 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) /* The command was handled, status is a separate consideration */ return 1; + } else if (ret == STAT_SET_INVALID) { + /* The command was acknowledged by shared handler, but not + * valid in current circumstances - do not pass to driver */ + return 1; } /* else try other handler(s) */ /* try the driver-provided handler if present */ From cf4414d1f85bf8750a3fd1a32091614686cfa4d6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:07:26 +0200 Subject: [PATCH 0705/1232] drivers/main.c, NEWS: constrain INSTCMD "driver.killpower" by "driver.flag.allow_killpower" setting [#1917] Closes: #1917 --- NEWS | 4 +++- docs/man/ups.conf.txt | 7 ++++++ drivers/main.c | 50 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index baca518b23..a5c4d7ee96 100644 --- a/NEWS +++ b/NEWS @@ -287,7 +287,9 @@ https://github.com/networkupstools/nut/milestone/8 :; upsrw -s driver.debug=-1 remoteUPS@1.2.3.4 ------ + -and a `driver.killpower` instant command [#1917] +and a `driver.killpower` instant command (for safety, must be unlocked by + `driver.flag.allow_killpower` protocol setting or `allow_killpower` + configuration flag) [#1917] - Implemented basic support for `ups.conf` reloading in NUT drivers, currently limited to `SIGHUP` handling and with a goal of changing diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index dcf4c0a1aa..314c2f7029 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -197,6 +197,13 @@ set this to -1. + The default value for this parameter is 0. +*allow_killpower*:: +Optional. This allows you to request `driver.killpower` instant command, +to immediately call the driver-specific default implementation of +`upsdrv_shutdown()` method, for same effect as when a NUT driver is +started with `-k` command-line flag. This option can be toggled with +linkman:upsrw[8] as `driver.flag.allow_killpower` during run-time. + *desc*:: Optional. This allows you to set a brief description that upsd will provide diff --git a/drivers/main.c b/drivers/main.c index f9561c5975..178a01c269 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -571,11 +571,19 @@ int main_instcmd(const char *cmdname, const char *extra) { cmdname, extra, NUT_STRARG(upsname)); if (!strcmp(cmdname, "driver.killpower")) { - upslogx(LOG_WARNING, "Requesting UPS [%s] to power off, " - "as/if handled by its driver by default (may exit), " - "due to socket protocol request", NUT_STRARG(upsname)); - upsdrv_shutdown(); - return STAT_INSTCMD_HANDLED; + if (!strcmp("1", dstate_getinfo("driver.flag.allow_killpower"))) { + upslogx(LOG_WARNING, "Requesting UPS [%s] to power off, " + "as/if handled by its driver by default (may exit), " + "due to socket protocol request", NUT_STRARG(upsname)); + upsdrv_shutdown(); + return STAT_INSTCMD_HANDLED; + } else { + upslogx(LOG_WARNING, "Got socket protocol request for UPS [%s] " + "to power off, but driver.flag.allow_killpower does not" + "permit this - request was currently ignored!", + NUT_STRARG(upsname)); + return STAT_INSTCMD_INVALID; + } } /* By default, the driver-specific values are @@ -609,6 +617,26 @@ int main_setvar(const char *varname, const char *val) { } } + if (!strcmp(varname, "driver.flag.allow_killpower")) { + int num = 0; + if (str_to_int(val, &num, 10)) { + if (num <= 0) { + num = 0; + } else num = 1; + } else { + /* support certain strings */ + if (!strncmp(val, "enable", 6) /* "enabled" matches too */ + || !strcmp(val, "true") + || !strcmp(val, "yes") + || !strcmp(val, "on") + ) num = 1; + } + + upsdebugx(1, "%s: Setting %s=%d", __func__, varname, num); + dstate_setinfo("driver.flag.allow_killpower", "%d", num); + return STAT_SET_HANDLED; + } + /* By default, the driver-specific values are * unknown to shared standard handler */ upsdebugx(2, "shared %s() does not handle variable %s, " @@ -660,6 +688,16 @@ static int main_arg(char *var, char *val) return 1; /* handled */ } + if (!strcmp(var, "allow_killpower")) { + if (reload_flag) { + upsdebugx(6, "%s: SKIP: flag var='%s' currently can not be reloaded " + "(but may be changed by protocol SETVAR)", __func__, var); + } else { + dstate_setinfo("driver.flag.allow_killpower", "1"); + } + return 1; /* handled */ + } + /* any other flags are for the driver code */ if (!val) return 0; /* unhandled, pass it through to the driver */ @@ -1800,6 +1838,8 @@ int main(int argc, char **argv) writepid(pidfn); /* PID changes when backgrounding */ } + dstate_setinfo("driver.flag.allow_killpower", "0"); + dstate_setflags("driver.flag.allow_killpower", ST_FLAG_RW | ST_FLAG_NUMBER); dstate_addcmd("driver.killpower"); dstate_setinfo("driver.state", "quiet"); From f4a65872a21930bb481c0cca785e3a219df88d8e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:41:12 +0200 Subject: [PATCH 0706/1232] upsd, upsdrvctl, drivers, upsmon, upssched progs and docs, NEWS: introduce NUT_DEBUG_LEVEL envvar support (if no "-D" option(s) among CLI args) [#1915] Closes: #1915 --- NEWS | 6 ++++++ clients/upsmon.c | 13 +++++++++++++ clients/upssched.c | 12 ++++++++++++ docs/man/nutupsdrv.txt | 4 ++++ docs/man/upsd.txt | 4 ++++ docs/man/upsdrvctl.txt | 4 ++++ docs/man/upsmon.txt | 7 +++++++ docs/man/upssched.txt | 7 +++++++ drivers/main.c | 13 +++++++++++++ drivers/upsdrvctl.c | 12 ++++++++++++ server/upsd.c | 13 +++++++++++++ 11 files changed, 95 insertions(+) diff --git a/NEWS b/NEWS index a5c4d7ee96..d5bc0a2f21 100644 --- a/NEWS +++ b/NEWS @@ -272,6 +272,12 @@ https://github.com/networkupstools/nut/milestone/8 `nut-server.service` as `upsd.service`, and `nut-monitor.service` as `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Numerous daemons (`upsd`, `upsmon`, drivers, `upsdrvctl`, `upssched`) + which accepted `-D` option for debug setting previously, now can also + honour a `NUT_DEBUG_LEVEL=NUM` environment variable if no `-D` arguments + were provided. Unlike those arguments, the environment variable does + not enforce that daemons run in foreground mode by default [#1915] + - Implemented generic support for INSTCMD and SETVAR use-cases shared by all drivers, and in particular to see and change active debug verbosity using the driver-server and server-client protocol (at higher priority diff --git a/clients/upsmon.c b/clients/upsmon.c index e827bc2020..1dc51aaa2e 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -2525,6 +2525,19 @@ 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) { + 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 */ + } + /* Note: "cmd" may be non-trivial to command that instance by * explicit PID number or lookup in PID file (error if absent). * Otherwise, we are being asked to start and "cmd" is 0/NULL - diff --git a/clients/upssched.c b/clients/upssched.c index e597694b2f..fb82321186 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1389,6 +1389,18 @@ 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 < 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; + } /* else follow -D settings */ + } /* else nothing to bother about */ + } + /* normally we don't have stderr, so get this going to syslog early */ open_syslog(prog); syslogbit_set(); diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index 01ddbf57a7..e67a461682 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -180,6 +180,10 @@ to start and where the hardware is attached. ENVIRONMENT VARIABLES --------------------- +*NUT_DEBUG_LEVEL* sets default debug verbosity if no *-D* arguments +were provided on command line, but does not request that the daemon +runs in foreground mode. + *NUT_CONFPATH* is the path name of the directory that contains `upsd.conf` and other configuration files. If this variable is not set, *upsd* uses a built-in default, which is often `/usr/local/ups/etc`. diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index 1debe7f9a5..eb2358c301 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -150,6 +150,10 @@ linkman:ups.conf[5]. ENVIRONMENT VARIABLES --------------------- +*NUT_DEBUG_LEVEL* sets default debug verbosity if no *-D* arguments +were provided on command line, but does not request that the daemon +runs in foreground mode. + *NUT_CONFPATH* is the path name of the directory that contains `upsd.conf` and other configuration files. If this variable is not set, *upsd* uses a built-in default, which is often `/usr/local/ups/etc`. diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 2bc77e5a5d..5452199ff9 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -111,6 +111,10 @@ It can be overridden by `NUT_IGNORE_NOWAIT` environment variable ENVIRONMENT VARIABLES --------------------- +*NUT_DEBUG_LEVEL* sets default debug verbosity if no *-D* arguments +were provided on command line, but does not request that the daemon +runs in foreground mode. + *NUT_CONFPATH* is the path name of the directory that contains `upsd.conf` and other configuration files. If this variable is not set, *upsdrvctl* the driver use a built-in default, which is often diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index f78990583b..2c591d0df1 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -481,6 +481,13 @@ those values, you *must* stop upsmon and start it back up. upsmon will warn you in the syslog if you make changes to either of those values during a reload. +ENVIRONMENT VARIABLES +--------------------- + +*NUT_DEBUG_LEVEL* sets default debug verbosity if no *-D* arguments +were provided on command line, but does not request that the daemon +runs in foreground mode. + FILES ----- diff --git a/docs/man/upssched.txt b/docs/man/upssched.txt index 0fb033b973..67fd62f7b4 100644 --- a/docs/man/upssched.txt +++ b/docs/man/upssched.txt @@ -101,6 +101,13 @@ when there are none running. If the timer daemon isn't running, there are no timers to cancel, and furthermore there is no need to start a clock-watcher. So, it skips that step and exits sooner. +ENVIRONMENT VARIABLES +--------------------- + +*NUT_DEBUG_LEVEL* sets default debug verbosity if no *-D* arguments +were provided on command line, but does not request that the daemon +runs in foreground mode. + FILES ----- diff --git a/drivers/main.c b/drivers/main.c index 178a01c269..fdb8527c30 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1528,6 +1528,19 @@ int main(int argc, char **argv) } } /* else: default remains `background_flag==-1` where nonzero is true */ + { /* 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) { + 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 */ + } + /* Since debug mode dumps from drivers are often posted to mailing list * or issue tracker, as well as viewed locally, it can help to know the * build options involved when troubleshooting (especially when needed diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index ec04cd14a4..100d436ea4 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -900,6 +900,18 @@ 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 < 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; + } /* else follow -D settings */ + } /* else nothing to bother about */ + } + argc -= optind; argv += optind; diff --git a/server/upsd.c b/server/upsd.c index 1c90267a54..b08863000c 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1695,6 +1695,19 @@ 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) { + 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 */ + } + /* Note: "cmd" may be non-trivial to command that instance by * explicit PID number or lookup in PID file (error if absent). * Otherwise, we are being asked to start and "cmd" is 0/NULL - From 725625416aeb1fcf38625ef3372cf34d05a87777 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:42:06 +0200 Subject: [PATCH 0707/1232] clients/upssched.c: debugging does not impact backgrounding (update help text) --- clients/upssched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/upssched.c b/clients/upssched.c index fb82321186..279b101812 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1355,7 +1355,7 @@ static void help(const char *arg_progname) printf("Practical behavior is managed by UPSNAME and NOTIFYTYPE envvars\n"); printf("\nUsage: %s [OPTIONS]\n\n", arg_progname); - printf(" -D raise debugging level (and stay foreground by default)\n"); + printf(" -D raise debugging level\n"); printf(" -V display the version of this software\n"); printf(" -h display this help\n"); From dab21bb32bf9c3ef6be1f112a7f6bf3354fba2cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:42:30 +0200 Subject: [PATCH 0708/1232] clients/upssched.c: comment how checkconf() is the processing loop --- clients/upssched.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clients/upssched.c b/clients/upssched.c index 279b101812..aa1593240a 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1415,6 +1415,9 @@ int main(int argc, char **argv) } /* see if this matches anything in the config file */ + /* This is actually the processing loop: + * checkconf -> conf_arg -> parse_at -> sendcmd -> daemon if needed + */ checkconf(); exit(EXIT_SUCCESS); From b2146cac44c5b53bcd8935aec3ce5a2bb60afca8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 15:54:35 +0200 Subject: [PATCH 0709/1232] docs/man/upssched.txt: mention UPSNAME and NOTIFYTYPE among supported envvars --- docs/man/upssched.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/man/upssched.txt b/docs/man/upssched.txt index 67fd62f7b4..c05e84d5c0 100644 --- a/docs/man/upssched.txt +++ b/docs/man/upssched.txt @@ -108,6 +108,9 @@ ENVIRONMENT VARIABLES were provided on command line, but does not request that the daemon runs in foreground mode. +*UPSNAME* and *NOTIFYTYPE* are required, as detailed above. They are +set by `upsmon` when it calls `upssched` as its choice of `NOTIFYCMD`. + FILES ----- From c24c24023e2574804f6720fba9a4d8e15d3f4eef Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 16:02:48 +0200 Subject: [PATCH 0710/1232] docs: update about NUT_*PATH envvars support --- docs/man/nutupsdrv.txt | 9 +++++---- docs/man/upsdrvctl.txt | 9 +++++++-- docs/man/upsmon.txt | 4 ++++ docs/man/upssched.txt | 4 ++++ 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index e67a461682..039f791ba1 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -185,12 +185,13 @@ were provided on command line, but does not request that the daemon runs in foreground mode. *NUT_CONFPATH* is the path name of the directory that contains -`upsd.conf` and other configuration files. If this variable is not set, -*upsd* uses a built-in default, which is often `/usr/local/ups/etc`. +`ups.conf` and other configuration files. If this variable is not set, +drivers use a built-in default, which is often `/usr/local/ups/etc`. *NUT_STATEPATH* is the path name of the directory in which -*upsd* keeps state information. If this variable is not set, -*upsd* uses a built-in default, which is often `/var/state/ups`. +*upsd* and drivers keep shared state information. If this variable +is not set, *upsd* and drivers use a built-in default, which is often +`/var/state/ups`. The *STATEPATH* directive in linkman:upsd.conf[5] overrides this variable. *NUT_ALTPIDPATH* is the path name of the directory in which diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 5452199ff9..fe3c903127 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -116,10 +116,15 @@ were provided on command line, but does not request that the daemon runs in foreground mode. *NUT_CONFPATH* is the path name of the directory that contains -`upsd.conf` and other configuration files. If this variable is not set, -*upsdrvctl* the driver use a built-in default, which is often +`ups.conf` and other configuration files. If this variable is not set, +*upsdrvctl* (and the drivers) use a built-in default, which is often `/usr/local/ups/etc`. +*NUT_ALTPIDPATH* is the path name of the directory in which +*upsd* and drivers store .pid files. If this variable is not set, +*upsd* and drivers use either *NUT_STATEPATH* if set, or ALTPIDPATH if set, +or otherwise the built-in default *STATEPATH*. + DIAGNOSTICS ----------- diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index 2c591d0df1..dc49d97ef5 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -488,6 +488,10 @@ ENVIRONMENT VARIABLES were provided on command line, but does not request that the daemon runs in foreground mode. +*NUT_CONFPATH* is the path name of the directory that contains +`upsmon.conf` and other configuration files. If this variable is not set, +*upsmon* uses a built-in default, which is often `/usr/local/ups/etc`. + FILES ----- diff --git a/docs/man/upssched.txt b/docs/man/upssched.txt index c05e84d5c0..3c582fc719 100644 --- a/docs/man/upssched.txt +++ b/docs/man/upssched.txt @@ -111,6 +111,10 @@ runs in foreground mode. *UPSNAME* and *NOTIFYTYPE* are required, as detailed above. They are set by `upsmon` when it calls `upssched` as its choice of `NOTIFYCMD`. +*NUT_CONFPATH* is the path name of the directory that contains +`upssched.conf` and other configuration files. If this variable is not set, +*upssched* uses a built-in default, which is often `/usr/local/ups/etc`. + FILES ----- From ce714fa3b7e5a6ba33fca8a4b1bd24f694d3138f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 16:42:25 +0200 Subject: [PATCH 0711/1232] docs/sock-protocol.txt, drivers/dstate.{c,h}: extend driver-server socket protocol with (NO)BROADCAST option [#1914] --- NEWS | 5 +++++ docs/nut.dict | 4 +++- docs/sock-protocol.txt | 21 +++++++++++++++++++++ drivers/dstate.c | 41 +++++++++++++++++++++++++++++++++++++++++ drivers/dstate.h | 1 + 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d5bc0a2f21..34ee250a45 100644 --- a/NEWS +++ b/NEWS @@ -272,6 +272,11 @@ https://github.com/networkupstools/nut/milestone/8 `nut-server.service` as `upsd.service`, and `nut-monitor.service` as `upsmon.service` (so simple `systemctl reload upsd` can work) [#1777] + - Extended driver-server socket protocol with `BROADCAST (num)` keyword, + and a `NOBROADCAST` as a shortcut for `BROADCAST 0`. This allows clients + to toggle whether they want to receive `send_to_all()` updates from a + driver, or only answers to requests they send [#1914] + - Numerous daemons (`upsd`, `upsmon`, drivers, `upsdrvctl`, `upssched`) which accepted `-D` option for debug setting previously, now can also honour a `NUT_DEBUG_LEVEL=NUM` environment variable if no `-D` arguments diff --git a/docs/nut.dict b/docs/nut.dict index c0fe9fea98..2246fd590e 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3119 utf-8 +personal_ws-1.1 en 3121 utf-8 AAS ABI ACFAIL @@ -738,6 +738,7 @@ NNNNNNNN NNNNNNNNNN NNNNNNNNNNNNNNNNNNN NOAUTH +NOBROADCAST NOCOMM NOCOMMWARNTIME NOCONF @@ -2740,6 +2741,7 @@ snmpwalk snprintf snprintfcat snr +socat sockdebug socomec solaris diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index 42768ba967..b5ab3edf4b 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -14,6 +14,11 @@ In terms of communications, each driver is a server on the Unix socket a client which knows where to find such sockets, how they are named, and connects to all of them to send commands and receive data updates. +During development, it is possible to use tools like `socat` to connect +to the socket (you may want to enable `NOBROADCAST` mode soon), e.g. + + socat - UNIX-CONNECT:/var/state/ups/dummy-ups-UPS1 + Formatting ---------- @@ -237,6 +242,22 @@ The server can tell when it has a full copy of the data by waiting for DUMPDONE. That special response from the driver is sent once the entire set has been transmitted. +NOBROADCAST +~~~~~~~~~~~ + +This connection does not want to receive broadcast messages (implemented +by `send_to_all()` method in `dstate.c`). Default is to receive everything. + +BROADCAST (NUM) +~~~~~~~~~~~~~~~ + +This connection specified whether it wants to receive broadcast messages +(implemented by `send_to_all()` method in `dstate.c`), and by default +enables that -- unless disabled by providing an optional zero or negative +numeric argument. Note that initial default is to receive everything, so +this command may be useful for connections that disabled broadcasts at +some point. + Design notes ------------ diff --git a/drivers/dstate.c b/drivers/dstate.c index 326ce7fd78..56019e9e21 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -270,6 +270,8 @@ static void send_to_all(const char *fmt, ...) for (conn = connhead; conn; conn = cnext) { cnext = conn->next; + if (conn->nobroadcast) + continue; #ifndef WIN32 ret = write(conn->fd, buf, buflen); @@ -566,6 +568,7 @@ static void sock_connect(TYPE_FD sock) NULL, &(conn->read_overlapped)); #endif + conn->nobroadcast = 0; pconf_init(&conn->ctx, NULL); if (connhead) { @@ -715,6 +718,44 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) return 1; } + if (!strcasecmp(arg[0], "NOBROADCAST")) { + char buf[SMALLBUF]; + conn->nobroadcast = 1; + snprintf(buf, sizeof(buf), +#ifndef WIN32 + "socket %d" +#else + "handle %p" +#endif + , conn->fd); + upsdebugx(1, "%s: %s requested NOBROADCAST mode", + __func__, buf); + return 1; + } + + /* BROADCAST <0|1> */ + if (!strcasecmp(arg[0], "BROADCAST")) { + int i; + char buf[SMALLBUF]; + conn->nobroadcast = 0; + if (numarg > 1 && str_to_int(arg[1], &i, 10)) { + if (i < 1) + conn->nobroadcast = 1; + } + snprintf(buf, sizeof(buf), +#ifndef WIN32 + "socket %d" +#else + "handle %p" +#endif + , conn->fd); + upsdebugx(1, + "%s: %s requested %sBROADCAST mode", + __func__, buf, + conn->nobroadcast ? "NO" : ""); + return 1; + } + if (numarg < 2) { return 0; } diff --git a/drivers/dstate.h b/drivers/dstate.h index f21c692c2e..c5b6111a5d 100644 --- a/drivers/dstate.h +++ b/drivers/dstate.h @@ -53,6 +53,7 @@ typedef struct conn_s { PCONF_CTX_t ctx; struct conn_s *prev; struct conn_s *next; + int nobroadcast; /* connections can request to ignore send_to_all() updates */ } conn_t; extern struct ups_handler upsh; From bdaafda56ab0b72ddeba5272eb0fc61f57d3e5f9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 17:08:56 +0200 Subject: [PATCH 0712/1232] driver/(main|dstate).(c|h): extend main_instcmd()/main_setvar() with knowledge of conn_t involved [#1914]\ --- drivers/dstate.c | 4 ++-- drivers/dstate.h | 4 ++-- drivers/main.c | 36 ++++++++++++++++++++++++++++++------ drivers/main.h | 4 ++-- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index 56019e9e21..97b9999571 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -784,7 +784,7 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) upsdebugx(3, "%s: TRACKING = %s", __func__, cmdid); /* try the handler shared by all drivers first */ - ret = main_instcmd(arg[1], arg[2]); + ret = main_instcmd(arg[1], arg[2], conn); if (ret == STAT_INSTCMD_HANDLED) { /* send back execution result */ if (cmdid) @@ -837,7 +837,7 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) } /* try the handler shared by all drivers first */ - ret = main_setvar(arg[1], arg[2]); + ret = main_setvar(arg[1], arg[2], conn); if (ret == STAT_SET_HANDLED) { /* send back execution result */ if (setid) diff --git a/drivers/dstate.h b/drivers/dstate.h index c5b6111a5d..ec26056cf5 100644 --- a/drivers/dstate.h +++ b/drivers/dstate.h @@ -30,8 +30,6 @@ #include "parseconf.h" #include "upshandler.h" -#include "main.h" /* for set_exit_flag() */ - #ifdef WIN32 # include "wincompat.h" #endif @@ -56,6 +54,8 @@ typedef struct conn_s { int nobroadcast; /* connections can request to ignore send_to_all() updates */ } conn_t; +#include "main.h" /* for set_exit_flag(); uses conn_t itself */ + extern struct ups_handler upsh; /* asynchronous (nonblocking) Vs synchronous (blocking) I/O diff --git a/drivers/main.c b/drivers/main.c index fdb8527c30..db93220b17 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -566,9 +566,21 @@ void addvar(int vartype, const char *name, const char *desc) } /* handle instant commands common for all drivers */ -int main_instcmd(const char *cmdname, const char *extra) { - upsdebugx(2, "entering main_instcmd(%s, %s) for [%s]", - cmdname, extra, NUT_STRARG(upsname)); +int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { + char buf[SMALLBUF]; + if (conn) + snprintf(buf, sizeof(buf), +#ifndef WIN32 + "socket %d" +#else + "handle %p" +#endif + , conn->fd); + else + snprintf(buf, sizeof(buf), "(null)"); + + upsdebugx(2, "entering main_instcmd(%s, %s) for [%s] on %s", + cmdname, extra, NUT_STRARG(upsname), buf); if (!strcmp(cmdname, "driver.killpower")) { if (!strcmp("1", dstate_getinfo("driver.flag.allow_killpower"))) { @@ -595,9 +607,21 @@ int main_instcmd(const char *cmdname, const char *extra) { } /* handle setting variables common for all drivers */ -int main_setvar(const char *varname, const char *val) { - upsdebugx(2, "entering main_setvar(%s, %s) for [%s]", - varname, val, NUT_STRARG(upsname)); +int main_setvar(const char *varname, const char *val, conn_t *conn) { + char buf[SMALLBUF]; + if (conn) + snprintf(buf, sizeof(buf), +#ifndef WIN32 + "socket %d" +#else + "handle %p" +#endif + , conn->fd); + else + snprintf(buf, sizeof(buf), "(null)"); + + upsdebugx(2, "entering main_setvar(%s, %s) for [%s] on %s", + varname, val, NUT_STRARG(upsname), buf); if (!strcmp(varname, "driver.debug")) { int num; diff --git a/drivers/main.h b/drivers/main.h index 1300bcc532..06997713b7 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -33,12 +33,12 @@ void set_exit_flag(int sig); /* handle instant commands common for all drivers * (returns STAT_INSTCMD_* state values per enum in upshandler.h) */ -int main_instcmd(const char *cmdname, const char *extra); +int main_instcmd(const char *cmdname, const char *extra, conn_t *conn); /* handle setting variables common for all drivers * (returns STAT_SET_* state values per enum in upshandler.h) */ -int main_setvar(const char *varname, const char *val); +int main_setvar(const char *varname, const char *val, conn_t *conn); /* main calls this driver function - it needs to call addvar */ void upsdrv_makevartable(void); From d45e547bf9620d4841b71427c3963a17e0894ae9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 20 Apr 2023 17:09:44 +0200 Subject: [PATCH 0713/1232] driver/main.c: main_instcmd() with basic "driver.reload" and "driver.reload-or-exit" support [#1903, #1914] --- drivers/main.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index db93220b17..9e8f201b0d 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -115,6 +115,7 @@ static int dump_data = 0; /* Store the update_count requested */ /* pre-declare some private methods used */ static void assign_debug_level(void); +static void set_reload_flag(int sig); /* print the driver banner */ void upsdrv_banner (void) @@ -598,6 +599,20 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { } } + if (!strcmp(cmdname, "driver.reload")) { + set_reload_flag(1); + /* TODO: sync mode to track that reload finished, and how? + * Especially to know if there were values we can not change + * on the fly, so caller may want to restart the driver itself. + */ + return STAT_INSTCMD_HANDLED; + } + + if (!strcmp(cmdname, "driver.reload-or-exit")) { + set_reload_flag(SIGUSR1); + return STAT_INSTCMD_HANDLED; + } + /* By default, the driver-specific values are * unknown to shared standard handler */ upsdebugx(2, "shared %s() does not handle command %s, " From 143ac8c2a2e28250f2a2c35551db897095efee94 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:11:57 +0200 Subject: [PATCH 0714/1232] server/sockdebug.c: #include "nut_stdint.h" for PRI* macros --- server/sockdebug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server/sockdebug.c b/server/sockdebug.c index 8f87f3b4ed..98667b44bd 100644 --- a/server/sockdebug.c +++ b/server/sockdebug.c @@ -28,6 +28,7 @@ #include "common.h" #include "parseconf.h" +#include "nut_stdint.h" PCONF_CTX_t sock_ctx; From d30f33e1ea98aeae1f7e93404fdaa7e082c2aa90 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:12:10 +0200 Subject: [PATCH 0715/1232] server/sockdebug.c: check return of fgets() --- server/sockdebug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/sockdebug.c b/server/sockdebug.c index 98667b44bd..62fbe2414d 100644 --- a/server/sockdebug.c +++ b/server/sockdebug.c @@ -159,7 +159,10 @@ int main(int argc, char **argv) if (FD_ISSET(fileno(stdin), &rfds)) { char buf[SMALLBUF]; - fgets(buf, sizeof(buf), stdin); + if (!fgets(buf, sizeof(buf), stdin)) { + perror("fgets from stdin"); + exit(EXIT_FAILURE); + } ret = write(sockfd, buf, strlen(buf)); From e1c86ec0711f10eaeabb00873e0429bfad813def Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:20:52 +0200 Subject: [PATCH 0716/1232] docs/sock-protocol.txt: suggest also server/sockdebug for dev/testing --- docs/sock-protocol.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index b5ab3edf4b..0e51165a9a 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -19,6 +19,12 @@ to the socket (you may want to enable `NOBROADCAST` mode soon), e.g. socat - UNIX-CONNECT:/var/state/ups/dummy-ups-UPS1 +For more insight, NUT provides an optional tool of its own (not built +by default), the `sockdebug`: + + (cd server && make sockdebug) && \ + ./server/sockdebug /var/state/ups/dummy-ups-UPS1 + Formatting ---------- From 2667bb8f7541b6531e9b2f2a430c400c22d06e45 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:21:42 +0200 Subject: [PATCH 0717/1232] server/sockdebug.c, server/pipedebug.c: support -h/--help on CLI --- server/pipedebug.c | 4 +++- server/sockdebug.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/server/pipedebug.c b/server/pipedebug.c index a69b8b5bb1..5afbafc4c9 100644 --- a/server/pipedebug.c +++ b/server/pipedebug.c @@ -131,7 +131,9 @@ int main(int argc, char **argv) HANDLE pipefd; HANDLE thread[2]; - if (argc != 2) { + if (argc != 2 + || (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) + ) { fprintf(stderr, "usage: %s \n", prog); fprintf(stderr, " %s apcsmart-com1\n", argv[0]); diff --git a/server/sockdebug.c b/server/sockdebug.c index 62fbe2414d..d8dbd6535c 100644 --- a/server/sockdebug.c +++ b/server/sockdebug.c @@ -124,7 +124,9 @@ int main(int argc, char **argv) const char *prog = xbasename(argv[0]); int ret, sockfd; - if (argc != 2) { + if (argc != 2 + || (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) + ) { fprintf(stderr, "usage: %s \n", prog); fprintf(stderr, " %s /var/state/ups/apcsmart-ttyS1.newsock\n", argv[0]); From 7a8e20e16fde5cdb4fff7bc7b8de0843b99d26cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:22:59 +0200 Subject: [PATCH 0718/1232] server/pipedebug.c: whitespace fixes (indentations et al) --- server/pipedebug.c | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/server/pipedebug.c b/server/pipedebug.c index 5afbafc4c9..0f7a39c248 100644 --- a/server/pipedebug.c +++ b/server/pipedebug.c @@ -1,4 +1,4 @@ -/* pipe.c - Network UPS Tools driver-server pipe debugger +/* pipe.c - Network UPS Tools driver-server pipe debugger (WIN32 builds) Copyright (C) 2012 Frederic Bohe @@ -26,45 +26,45 @@ PCONF_CTX_t pipe_ctx; static void pipe_arg(int numarg, char **arg) { - int i; + int i; - printf("numarg=%d : ", numarg); + printf("numarg=%d : ", numarg); - for (i = 0; i < numarg; i++) - printf("[%s] ", arg[i]); + for (i = 0; i < numarg; i++) + printf("[%s] ", arg[i]); - printf("\n"); + printf("\n"); } static HANDLE pipe_connect(const char *pipefn) { - HANDLE fd; - char pipename[SMALLBUF]; - BOOL result = FALSE; + HANDLE fd; + char pipename[SMALLBUF]; + BOOL result = FALSE; - snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\%s", pipefn); + snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\%s", pipefn); - result = WaitNamedPipe(pipename,NMPWAIT_USE_DEFAULT_WAIT); + result = WaitNamedPipe(pipename,NMPWAIT_USE_DEFAULT_WAIT); - if( result == FALSE ) { + if( result == FALSE ) { printf("WaitNamedPipe : %d\n",GetLastError()); exit(EXIT_FAILURE); - } - - fd = CreateFile( - pipename, // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes FIXME - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, // enable async IO - NULL); // no template file - - if (fd == INVALID_HANDLE_VALUE) { + } + + fd = CreateFile( + pipename, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes FIXME + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // enable async IO + NULL); // no template file + + if (fd == INVALID_HANDLE_VALUE) { printf("CreateFile : %d\n",GetLastError()); exit(EXIT_FAILURE); - } + } return fd; } @@ -89,18 +89,18 @@ static void read_buf(char * buf, DWORD num) DWORD WINAPI ReadThread( LPVOID lpParameter ) { - HANDLE pipefd = *((HANDLE *)lpParameter); - DWORD bytes_read; - char pipe_buf[SMALLBUF]; - OVERLAPPED pipe_overlapped; + HANDLE pipefd = *((HANDLE *)lpParameter); + DWORD bytes_read; + char pipe_buf[SMALLBUF]; + OVERLAPPED pipe_overlapped; pconf_init(&pipe_ctx, NULL); - memset(&pipe_overlapped,0,sizeof(pipe_overlapped)); + memset(&pipe_overlapped,0,sizeof(pipe_overlapped)); pipe_overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); for (;;) { - memset(pipe_buf,0,sizeof(pipe_buf)); + memset(pipe_buf,0,sizeof(pipe_buf)); ReadFile(pipefd,pipe_buf,sizeof(pipe_buf),NULL,&pipe_overlapped); GetOverlappedResult(pipefd,&pipe_overlapped,&bytes_read,TRUE); read_buf(pipe_buf,bytes_read); @@ -109,15 +109,15 @@ DWORD WINAPI ReadThread( LPVOID lpParameter ) DWORD WINAPI WriteThread( LPVOID lpParameter ) { - HANDLE pipefd = *((HANDLE *)lpParameter); - HANDLE hStdin; - DWORD bytes_read; - char stdin_buf[SMALLBUF]; - OVERLAPPED pipe_overlapped; + HANDLE pipefd = *((HANDLE *)lpParameter); + HANDLE hStdin; + DWORD bytes_read; + char stdin_buf[SMALLBUF]; + OVERLAPPED pipe_overlapped; hStdin = GetStdHandle(STD_INPUT_HANDLE); - memset(&pipe_overlapped,0,sizeof(pipe_overlapped)); + memset(&pipe_overlapped,0,sizeof(pipe_overlapped)); pipe_overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); for (;;) { @@ -128,8 +128,8 @@ DWORD WINAPI WriteThread( LPVOID lpParameter ) int main(int argc, char **argv) { const char *prog = xbasename(argv[0]); - HANDLE pipefd; - HANDLE thread[2]; + HANDLE pipefd; + HANDLE thread[2]; if (argc != 2 || (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) From 0a8043a9f09ff4b10554c9fd3695bd01a05d0897 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:27:22 +0200 Subject: [PATCH 0719/1232] drivers/main.c: set_reload_flag (and SIGUSR1) are currently only for non-WIN32 builds [#1903, #1916] --- drivers/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 9e8f201b0d..27998fb647 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -115,7 +115,10 @@ static int dump_data = 0; /* Store the update_count requested */ /* pre-declare some private methods used */ static void assign_debug_level(void); +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ static void set_reload_flag(int sig); +#endif /* print the driver banner */ void upsdrv_banner (void) @@ -599,6 +602,8 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { } } +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ if (!strcmp(cmdname, "driver.reload")) { set_reload_flag(1); /* TODO: sync mode to track that reload finished, and how? @@ -612,6 +617,7 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { set_reload_flag(SIGUSR1); return STAT_INSTCMD_HANDLED; } +#endif /* By default, the driver-specific values are * unknown to shared standard handler */ From 4c1ceafdd99623273b9ffd61f6948d43891898d0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 11:31:07 +0200 Subject: [PATCH 0720/1232] drivers/main.c: un-hide assign_debug_level() for mock-driver builds aka DRIVERS_MAIN_WITHOUT_MAIN now that it is referenced in main_setvar() [#1903, #1285] --- drivers/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index 27998fb647..0bb932b9fa 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1115,7 +1115,6 @@ void do_upsconf_args(char *confupsname, char *var, char *val) } } -#ifndef DRIVERS_MAIN_WITHOUT_MAIN static void assign_debug_level(void) { /* CLI debug level can not be smaller than debug_min specified * in ups.conf, and value specified for a driver config section @@ -1181,6 +1180,7 @@ static void assign_debug_level(void) { dstate_setflags("driver.debug", ST_FLAG_RW | ST_FLAG_NUMBER); } +#ifndef DRIVERS_MAIN_WITHOUT_MAIN static void handle_reload_flag(void) { if (!reload_flag || exit_flag) return; From dd02dad6888b8b7a1b54e1a922511cdf6964c5db Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 12:02:55 +0200 Subject: [PATCH 0721/1232] drivers/main.c: main_instcmd()/main_setvar() POSIX/WIN32 preparation of string: satisfy platforms where snprintf is a macro [#1914] --- drivers/main.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 20edbba953..cbe525c1e0 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -608,13 +608,11 @@ void addvar(int vartype, const char *name, const char *desc) int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { char buf[SMALLBUF]; if (conn) - snprintf(buf, sizeof(buf), #ifndef WIN32 - "socket %d" + snprintf(buf, sizeof(buf), "socket %d", conn->fd); #else - "handle %p" + snprintf(buf, sizeof(buf), "handle %p", conn->fd); #endif - , conn->fd); else snprintf(buf, sizeof(buf), "(null)"); @@ -666,13 +664,11 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { int main_setvar(const char *varname, const char *val, conn_t *conn) { char buf[SMALLBUF]; if (conn) - snprintf(buf, sizeof(buf), #ifndef WIN32 - "socket %d" + snprintf(buf, sizeof(buf), "socket %d", conn->fd); #else - "handle %p" + snprintf(buf, sizeof(buf), "handle %p", conn->fd); #endif - , conn->fd); else snprintf(buf, sizeof(buf), "(null)"); From 9d45d6eac539e2051c9f3a5879e4ce8308d36c95 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 12:43:01 +0200 Subject: [PATCH 0722/1232] drivers/dstate.c: sock_arg() (NO)BROADCAST handling => POSIX/WIN32 preparation of string: satisfy platforms where snprintf is a macro [#1914] --- drivers/dstate.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index 97b9999571..3229ac57b8 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -721,13 +721,11 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) if (!strcasecmp(arg[0], "NOBROADCAST")) { char buf[SMALLBUF]; conn->nobroadcast = 1; - snprintf(buf, sizeof(buf), #ifndef WIN32 - "socket %d" + snprintf(buf, sizeof(buf), "socket %d", conn->fd); #else - "handle %p" + snprintf(buf, sizeof(buf), "handle %p", conn->fd); #endif - , conn->fd); upsdebugx(1, "%s: %s requested NOBROADCAST mode", __func__, buf); return 1; @@ -742,13 +740,11 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) if (i < 1) conn->nobroadcast = 1; } - snprintf(buf, sizeof(buf), #ifndef WIN32 - "socket %d" + snprintf(buf, sizeof(buf), "socket %d", conn->fd); #else - "handle %p" + snprintf(buf, sizeof(buf), "handle %p", conn->fd); #endif - , conn->fd); upsdebugx(1, "%s: %s requested %sBROADCAST mode", __func__, buf, From 7de906a116e8bcb1f3039ef0fdff2c465338d7fd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 13:22:42 +0200 Subject: [PATCH 0723/1232] common/common.c: vupslog(), nut_report_config_flags(): seems WIN32 needs fflush(stderr) --- common/common.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index c7c83498b3..93d420f80b 100644 --- a/common/common.c +++ b/common/common.c @@ -1109,7 +1109,7 @@ void nut_report_config_flags(void) now.tv_sec -= 1; } - if (xbit_test(upslog_flags, UPSLOG_STDERR)) + if (xbit_test(upslog_flags, UPSLOG_STDERR)) { fprintf(stderr, "%4.0f.%06ld\t[D1] Network UPS Tools version %s%s%s%s%s%s%s %s%s\n", difftime(now.tv_sec, upslog_start.tv_sec), (long)(now.tv_usec - upslog_start.tv_usec), @@ -1123,6 +1123,10 @@ void nut_report_config_flags(void) (config_flags && *config_flags != '\0' ? "configured with flags: " : "configured all by default guesswork"), (config_flags && *config_flags != '\0' ? config_flags : "") ); +#ifdef WIN32 + fflush(stderr); +#endif + } /* NOTE: May be ignored or truncated by receiver if that syslog server * (and/or OS sender) does not accept messages of such length */ @@ -1212,8 +1216,12 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) (long)(now.tv_usec - upslog_start.tv_usec)); } - if (xbit_test(upslog_flags, UPSLOG_STDERR)) + if (xbit_test(upslog_flags, UPSLOG_STDERR)) { fprintf(stderr, "%s\n", buf); +#ifdef WIN32 + fflush(stderr); +#endif + } if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) syslog(priority, "%s", buf); } From 090b40135ee164501c88db4afadcdd950d8b6877 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 13:27:15 +0200 Subject: [PATCH 0724/1232] common/common.c: vupslog(): only print timestamps to stderr if xbit_test(upslog_flags, UPSLOG_STDERR) at all, not just that the debug is enabled; also mark upslog_start when we first call the method, even if debu is not currently verbose (may change at run time) [#1903] --- common/common.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/common/common.c b/common/common.c index 93d420f80b..38383e401b 100644 --- a/common/common.c +++ b/common/common.c @@ -1197,26 +1197,29 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) #endif } - if (nut_debug_level > 0) { + /* Note: nowadays debug level can be changed during run-time, + * so mark the starting point whenever we first try to log */ + if (upslog_start.tv_sec == 0) { struct timeval now; - gettimeofday(&now, NULL); + upslog_start = now; + } - if (upslog_start.tv_sec == 0) { - upslog_start = now; - } + if (xbit_test(upslog_flags, UPSLOG_STDERR)) { + if (nut_debug_level > 0) { + struct timeval now; - if (upslog_start.tv_usec > now.tv_usec) { - now.tv_usec += 1000000; - now.tv_sec -= 1; - } + gettimeofday(&now, NULL); - fprintf(stderr, "%4.0f.%06ld\t", - difftime(now.tv_sec, upslog_start.tv_sec), - (long)(now.tv_usec - upslog_start.tv_usec)); - } + if (upslog_start.tv_usec > now.tv_usec) { + now.tv_usec += 1000000; + now.tv_sec -= 1; + } - if (xbit_test(upslog_flags, UPSLOG_STDERR)) { + fprintf(stderr, "%4.0f.%06ld\t", + difftime(now.tv_sec, upslog_start.tv_sec), + (long)(now.tv_usec - upslog_start.tv_usec)); + } fprintf(stderr, "%s\n", buf); #ifdef WIN32 fflush(stderr); From 4b3a3173ee8373324e55da65c7a2008a0c3709e0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 13:37:36 +0200 Subject: [PATCH 0725/1232] docs/sock-protocol.txt: clarify use of sockdebug in WIN32 builds --- docs/sock-protocol.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index 0e51165a9a..8adadd57d2 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -22,9 +22,14 @@ to the socket (you may want to enable `NOBROADCAST` mode soon), e.g. For more insight, NUT provides an optional tool of its own (not built by default), the `sockdebug`: + # POSIX (cd server && make sockdebug) && \ ./server/sockdebug /var/state/ups/dummy-ups-UPS1 + # WIN32 + (cd server && make sockdebug.exe) && \ + ./server/sockdebug.exe dummy-ups-UPS1 + Formatting ---------- From 644eb0078931d3d9b2a2cd477223a0014d75fad1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 13:38:04 +0200 Subject: [PATCH 0726/1232] server/pipedebug.c: seems WIN32 needs fflush(stdout) --- server/pipedebug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/pipedebug.c b/server/pipedebug.c index 0f7a39c248..b8e7f78fa1 100644 --- a/server/pipedebug.c +++ b/server/pipedebug.c @@ -34,6 +34,7 @@ static void pipe_arg(int numarg, char **arg) printf("[%s] ", arg[i]); printf("\n"); + fflush(stdout); } static HANDLE pipe_connect(const char *pipefn) @@ -143,6 +144,7 @@ int main(int argc, char **argv) pipefd = pipe_connect(argv[1]); printf("connected: fd %d\n", pipefd); + fflush(stdout); thread[0] = CreateThread( NULL, /* security */ From e41ffc110b03a1fccff693c8bbe1663739be36ac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 16:29:32 +0200 Subject: [PATCH 0727/1232] drivers/main.c: un-hide nut_debug_level_args for mock-driver builds aka DRIVERS_MAIN_WITHOUT_MAIN now that it is referenced in main_setvar()=>assign_debug_level() [#1903, #1285] --- drivers/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index cbe525c1e0..616e65a559 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -104,9 +104,7 @@ static int foreground = -1; * have more). Finally, it can also be set over socket * protocol, taking precedence over other inputs. */ -#ifndef DRIVERS_MAIN_WITHOUT_MAIN static int nut_debug_level_args = -1; -#endif static int nut_debug_level_global = -1; static int nut_debug_level_driver = -1; static int nut_debug_level_protocol = -1; From 45f9d1774bdf534ada4e119a5fe88240d42dc45c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 19:19:01 +0200 Subject: [PATCH 0728/1232] drivers/dstate.c: sock_arg(): if shared main_instcmd()/main_setvar() did recognize and somehow process the request, honour TRACKING if present [#1903, #1920] --- drivers/dstate.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index 3229ac57b8..a6b1b0e2fb 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -781,24 +781,25 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) /* try the handler shared by all drivers first */ ret = main_instcmd(arg[1], arg[2], conn); - if (ret == STAT_INSTCMD_HANDLED) { - /* send back execution result */ + if (ret != STAT_INSTCMD_UNKNOWN) { + /* The command was acknowledged by shared handler, and + * either handled successfully, or failed, or was not + * valid in current circumstances - in any case, we do + * not pass to driver-provided logic. */ + + /* send back execution result if requested */ if (cmdid) send_tracking(conn, cmdid, ret); /* The command was handled, status is a separate consideration */ return 1; - } else if (ret == STAT_INSTCMD_INVALID) { - /* The command was acknowledged by shared handler, but not - * valid in current circumstances - do not pass to driver */ - return 1; } /* else try other handler(s) */ /* try the driver-provided handler if present */ if (upsh.instcmd) { ret = upsh.instcmd(cmdname, cmdparam); - /* send back execution result */ + /* send back execution result if requested */ if (cmdid) send_tracking(conn, cmdid, ret); @@ -834,24 +835,25 @@ static int sock_arg(conn_t *conn, size_t numarg, char **arg) /* try the handler shared by all drivers first */ ret = main_setvar(arg[1], arg[2], conn); - if (ret == STAT_SET_HANDLED) { - /* send back execution result */ + if (ret != STAT_SET_UNKNOWN) { + /* The command was acknowledged by shared handler, and + * either handled successfully, or failed, or was not + * valid in current circumstances - in any case, we do + * not pass to driver-provided logic. */ + + /* send back execution result if requested */ if (setid) send_tracking(conn, setid, ret); /* The command was handled, status is a separate consideration */ return 1; - } else if (ret == STAT_SET_INVALID) { - /* The command was acknowledged by shared handler, but not - * valid in current circumstances - do not pass to driver */ - return 1; } /* else try other handler(s) */ /* try the driver-provided handler if present */ if (upsh.setvar) { ret = upsh.setvar(arg[1], arg[2]); - /* send back execution result */ + /* send back execution result if requested */ if (setid) send_tracking(conn, setid, ret); From 8226e2abbc4132b039420ac4cffcecede7a08447 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 21 Apr 2023 19:23:14 +0200 Subject: [PATCH 0729/1232] drivers/main.c: main(): register "driver.reload(-or-exit)" commands so `upsd` would accept them and `upscmd` can request them [#1903] --- drivers/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 616e65a559..c6a41cefb9 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -2122,6 +2122,12 @@ int main(int argc, char **argv) dstate_setflags("driver.flag.allow_killpower", ST_FLAG_RW | ST_FLAG_NUMBER); dstate_addcmd("driver.killpower"); +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ + dstate_addcmd("driver.reload"); + dstate_addcmd("driver.reload-or-exit"); +#endif + dstate_setinfo("driver.state", "quiet"); if (dump_data) { upsdebugx(1, "Driver initialization completed, beginning data dump (%d loops)", dump_data); From d2c6b7705ba403e1e2b1c962ae41461c95932f45 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 00:29:46 +0200 Subject: [PATCH 0730/1232] drivers/main.c: add socket-protocol handling for "driver.reload-or-error" INSTCMD [#1903, #1914] --- drivers/main.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index c6a41cefb9..a2a88466e4 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -120,8 +120,15 @@ static void assign_debug_level(void); #ifndef WIN32 /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ static void set_reload_flag(int sig); +# ifndef DRIVERS_MAIN_WITHOUT_MAIN +/* Returns a result code from INSTCMD enum values */ +static int handle_reload_flag(void); +# endif #endif +/* Set in do_ups_confargs() for consumers like handle_reload_flag() */ +static int reload_requires_restart = -1; + /* print the driver banner */ void upsdrv_banner (void) { @@ -423,10 +430,20 @@ int testvar_reloadable(const char *var, const char *val, int vartype) EXIT_SUCCESS #endif , "NUT driver reload-or-exit: setting %s was changed and requires a driver restart", var); + verdict = ( (!reload_flag) /* For initial config reads, legacy code trusted what it saw */ || tmp->reloadable /* set in addvar*() */ ); + + /* handle reload-or-error reports */ + if (verdict == 0) { + if (reload_requires_restart < 1) + reload_requires_restart = 1; + else + reload_requires_restart++; + } + goto finish; } } @@ -446,6 +463,17 @@ int testvar_reloadable(const char *var, const char *val, int vartype) verdict = 1; /* not found, may (re)load the definition */ finish: + switch (verdict) { + case -1: /* no-op for caller, same value remains */ + case 1: /* value may be (re-)applied */ + if (reload_requires_restart < 0) + reload_requires_restart = 0; + break; + + case 0: /* value may not be (re-)applied, but it may not have been required */ + break; + } + upsdebugx(6, "%s: verdict for (re)loading var=%s value: %d", __func__, NUT_STRARG(var), verdict); return verdict; @@ -515,10 +543,30 @@ int testval_reloadable(const char *var, const char *oldval, const char *newval, , "NUT driver reload-or-exit: setting %s was changed and requires a driver restart", var); /* For initial config reads, legacy code trusted what it saw */ verdict = ((!reload_flag) || reloadable); + + /* handle reload-or-error reports */ + if (verdict == 0) { + if (reload_requires_restart < 1) + reload_requires_restart = 1; + else + reload_requires_restart++; + } + goto finish; } finish: + switch (verdict) { + case -1: /* no-op for caller, same value remains */ + case 1: /* value may be (re-)applied */ + if (reload_requires_restart < 0) + reload_requires_restart = 0; + break; + + case 0: /* value may not be (re-)applied, but it may not have been required */ + break; + } + upsdebugx(6, "%s: verdict for (re)loading var=%s value: %d", __func__, NUT_STRARG(var), verdict); return verdict; @@ -648,6 +696,15 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { set_reload_flag(SIGUSR1); return STAT_INSTCMD_HANDLED; } + +# ifndef DRIVERS_MAIN_WITHOUT_MAIN + if (!strcmp(cmdname, "driver.reload-or-error")) { + /* sync-capable handling */ + set_reload_flag(1); + /* Returns a result code from INSTCMD enum values */ + return handle_reload_flag(); + } +# endif #endif /* By default, the driver-specific values are @@ -1210,9 +1267,12 @@ static void assign_debug_level(void) { } #ifndef DRIVERS_MAIN_WITHOUT_MAIN -static void handle_reload_flag(void) { +/* Returns a result code from INSTCMD enum values */ +static int handle_reload_flag(void) { + int ret; + if (!reload_flag || exit_flag) - return; + return STAT_INSTCMD_INVALID; upslogx(LOG_INFO, "Handling requested live reload of NUT driver configuration for [%s]", upsname); dstate_setinfo("driver.state", "reloading"); @@ -1226,8 +1286,25 @@ static void handle_reload_flag(void) { nut_debug_level_global = -1; nut_debug_level_driver = -1; - /* Call actual config reloading activity */ + /* Call actual config reloading activity, which + * eventually calls back do_upsconf_args() from + * this program. + */ + reload_requires_restart = -1; read_upsconf(); + + upsdebugx(1, "%s: read_upsconf() for [%s] completed, restart-required verdict was: %d", + __func__, upsname, reload_requires_restart); + + /* handle reload-or-error reports */ + if (reload_requires_restart < 1) { + /* -1 unchanged, 0 nobody complained and everyone confirmed */ + ret = STAT_INSTCMD_HANDLED; + } else { + /* 1+ entries required a restart */ + ret = STAT_INSTCMD_INVALID; + }; + /* TODO: Callbacks in drivers to re-parse configs? * Currently this reloadability relies on either * explicit reload_flag aware code called from the @@ -1243,7 +1320,9 @@ static void handle_reload_flag(void) { reload_flag = 0; dstate_setinfo("driver.state", "quiet"); upsnotify(NOTIFY_STATE_READY, NULL); - upslogx(LOG_INFO, "Completed requested live reload of NUT driver configuration for [%s]", upsname); + upslogx(LOG_INFO, "Completed requested live reload of NUT driver configuration for [%s]: %d", upsname, ret); + + return ret; } /* split -x foo=bar into 'foo' and 'bar' */ @@ -2126,6 +2205,9 @@ int main(int argc, char **argv) /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ dstate_addcmd("driver.reload"); dstate_addcmd("driver.reload-or-exit"); +# ifndef DRIVERS_MAIN_WITHOUT_MAIN + dstate_addcmd("driver.reload-or-error"); +# endif #endif dstate_setinfo("driver.state", "quiet"); From f4c84fbda35f93288d3c51bd09f65790642a258a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 01:01:43 +0200 Subject: [PATCH 0731/1232] drivers/main.c: main_instcmd(): set_reload_flag() by SIGCMD_* macros, not numbers [#1903, #1914] --- drivers/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index a2a88466e4..403b0a9558 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -684,7 +684,7 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { #ifndef WIN32 /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ if (!strcmp(cmdname, "driver.reload")) { - set_reload_flag(1); + set_reload_flag(SIGCMD_RELOAD); /* TODO: sync mode to track that reload finished, and how? * Especially to know if there were values we can not change * on the fly, so caller may want to restart the driver itself. @@ -693,14 +693,14 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { } if (!strcmp(cmdname, "driver.reload-or-exit")) { - set_reload_flag(SIGUSR1); + set_reload_flag(SIGCMD_RELOAD_OR_EXIT); return STAT_INSTCMD_HANDLED; } # ifndef DRIVERS_MAIN_WITHOUT_MAIN if (!strcmp(cmdname, "driver.reload-or-error")) { /* sync-capable handling */ - set_reload_flag(1); + set_reload_flag(SIGCMD_RELOAD); /* Returns a result code from INSTCMD enum values */ return handle_reload_flag(); } From 9bd4234de4b70e8f658ede5625b6625a37a8b892 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 01:02:47 +0200 Subject: [PATCH 0732/1232] drivers/main.c: main_instcmd(): add placeholder for "driver.reload-or-restart" support [#1903, #1914] --- drivers/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 403b0a9558..8bedcb5fef 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -697,6 +697,13 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { return STAT_INSTCMD_HANDLED; } +# ifdef SIGCMD_RELOAD_OR_RESTART + if (!strcmp(cmdname, "driver.reload-or-restart")) { + set_reload_flag(SIGCMD_RELOAD_OR_RESTART); + return STAT_INSTCMD_HANDLED; + } +# endif + # ifndef DRIVERS_MAIN_WITHOUT_MAIN if (!strcmp(cmdname, "driver.reload-or-error")) { /* sync-capable handling */ @@ -2208,6 +2215,9 @@ int main(int argc, char **argv) # ifndef DRIVERS_MAIN_WITHOUT_MAIN dstate_addcmd("driver.reload-or-error"); # endif +# ifdef SIGCMD_RELOAD_OR_RESTART + dstate_addcmd("driver.reload-or-restart"); +# endif #endif dstate_setinfo("driver.state", "quiet"); From d11b0fd78993dfe2aa6291d0aa80d656dea2caa7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 01:12:22 +0200 Subject: [PATCH 0733/1232] docs/man/nutupsdrv.txt: add placeholder for "-c reload-or-restart" CLI argument [#1903] --- docs/man/nutupsdrv.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index 25021ab3ad..a999b7f214 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -102,6 +102,13 @@ are: driver process if it encounters modified settings which can not be applied "on the fly" (so caller like systemd can launch another copy of the driver) +///////// + *reload-or-restart*;; reread configuration files, causing the + old driver process to close the device connection + and re-exec itself if it encounters modified settings + which can not be applied "on the fly" (may fail for + critical changes like run-time user/group accounts) +///////// *-P* 'pid':: Send the command signal above using specified PID number, rather than From f52b39567ee224df707a01a0114066ef9a082c01 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 03:54:44 +0200 Subject: [PATCH 0734/1232] drivers/upsdrvquery.{c,h}, drivers/Makefile.am: Introduce a socket protocol client for quickshot commands [#1903, #1914] --- drivers/Makefile.am | 9 +- drivers/upsdrvquery.c | 365 ++++++++++++++++++++++++++++++++++++++++++ drivers/upsdrvquery.h | 40 +++++ 3 files changed, 411 insertions(+), 3 deletions(-) create mode 100644 drivers/upsdrvquery.c create mode 100644 drivers/upsdrvquery.h diff --git a/drivers/Makefile.am b/drivers/Makefile.am index d6f4636223..3d945abd2f 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -10,7 +10,7 @@ $(top_builddir)/clients/libupsclient.la: dummy # (libtool version of the static lib, in order to access LTLIBOBJS) #FIXME: SERLIBS is only useful for LDADD_DRIVERS_SERIAL not for LDADD_COMMON LDADD_COMMON = $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la -LDADD_DRIVERS = libdummy.la $(LDADD_COMMON) +LDADD_DRIVERS = libdummy.la libdummy_upsdrvquery.la $(LDADD_COMMON) LDADD_DRIVERS_SERIAL = libdummy_serial.la $(LDADD_DRIVERS) $(SERLIBS) # most targets are serial drivers, so make this the default @@ -119,7 +119,7 @@ sbin_PROGRAMS = upsdrvctl # upsdrvctl: the all-singing all-dancing driver control program upsdrvctl_SOURCES = upsdrvctl.c -upsdrvctl_LDADD = $(LDADD_COMMON) +upsdrvctl_LDADD = $(LDADD_COMMON) libdummy_upsdrvquery.la # serial drivers: all of them use standard LDADD and CFLAGS al175_SOURCES = al175.c @@ -352,6 +352,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi nutdrv_qx_mecer.h nutdrv_qx_ablerex.h \ nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h nutdrv_qx_hunnox.h \ nutdrv_qx_voltronic.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 \ apc-pdu-mib.h apc-epdu-mib.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 \ @@ -363,11 +364,13 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi # because per-object CFLAGS can only be specified for libraries, not # for object files. This library is used during the build process, # and is not meant to be installed. -EXTRA_LTLIBRARIES = libdummy.la libdummy_serial.la +EXTRA_LTLIBRARIES = libdummy.la libdummy_serial.la libdummy_upsdrvquery.la libdummy_la_SOURCES = main.c dstate.c libdummy_la_LDFLAGS = -no-undefined -static libdummy_serial_la_SOURCES = serial.c libdummy_serial_la_LDFLAGS = -no-undefined -static +libdummy_upsdrvquery_la_SOURCES = upsdrvquery.c +libdummy_upsdrvquery_la_LDFLAGS = -no-undefined -static # The libdummy_mockdrv.la is used for unit-tests to mock a driver # with near-production codebase but without its standard main(). diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c new file mode 100644 index 0000000000..02d3ec7527 --- /dev/null +++ b/drivers/upsdrvquery.c @@ -0,0 +1,365 @@ +/* upsdrvquery.c - a single query shot over a driver socket, + tracked until a response arrives, returning + that line and closing a connection + + Copyright (C) 2023 Jim Klimov + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 "config.h" /* must be the first header */ + +#include +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#include +#else +#include "wincompat.h" +#endif + +#include "common.h" +#include "upsdrvquery.h" +#include "nut_stdint.h" + +TYPE_FD upsdrvquery_connect(const char *sockfn) { + TYPE_FD sockfd; + + /* Code borrowed from our numerous sock_connect() implems */ +#ifndef WIN32 + struct sockaddr_un sa; + ssize_t ret; + + memset(&sa, '\0', sizeof(sa)); + sa.sun_family = AF_UNIX; + snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", sockfn); + + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (sockfd < 0) { + upslog_with_errno(LOG_ERR, "open socket"); + return ERROR_FD; + } + + if (connect(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + upslog_with_errno(LOG_ERR, "connect to driver socket at %s", sockfn); + close(sockfd); + return ERROR_FD; + } + + ret = fcntl(sockfd, F_GETFL, 0); + if (ret < 0) { + upslog_with_errno(LOG_ERR, "fcntl get on driver socket %s failed", sockfn); + close(sockfd); + return ERROR_FD; + } + + if (fcntl(sockfd, F_SETFL, ret | O_NDELAY) < 0) { + upslog_with_errno(LOG_ERR, "fcntl set O_NDELAY on driver socket %s failed", sockfn); + close(sockfd); + return ERROR_FD; + } +#else + result = WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT); + + if (result == FALSE) { + upslog_with_errno(LOG_ERR, "WaitNamedPipe : %d\n", GetLastError()); + return ERROR_FD; + } + + sockfd = CreateFile( + pipename, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes FIXME + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // enable async IO + NULL); // no template file + + if (sockfd == INVALID_HANDLE_VALUE) { + upslog_with_errno(LOG_ERR, "CreateFile : %d\n", GetLastError()); + return ERROR_FD; + } +#endif /* WIN32 */ + + return sockfd; +} + +TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname) { + char pidfn[SMALLBUF]; +#ifndef WIN32 + struct stat fs; + snprintf(pidfn, sizeof(pidfn), "%s/%s-%s", + dflt_statepath(), drvname, upsname); + check_unix_socket_filename(pidfn); + if (stat(pidfn, &fs)) { + upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); + return ERROR_FD; + } +#else + snprintf(pidfn, sizeof(pidfn), "\\\\.\\pipe\\%s-%s", drvname, upsname); +#endif /* WIN32 */ + + return upsdrvquery_connect(pidfn); +} + +void upsdrvquery_close(TYPE_FD sockfd) { + if (INVALID_FD(sockfd)) + return; + +#ifndef WIN32 + close(sockfd); +#else + CloseHandle(sockfd); +#endif /* WIN32 */ +} + +ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, const size_t bufsz) { + ssize_t ret; + +#ifndef WIN32 + fd_set rfds; + + FD_ZERO(&rfds); + FD_SET(sockfd, &rfds); + + if (select(sockfd + 1, &rfds, NULL, NULL, &tv) < 0) { + upslog_with_errno(LOG_ERR, "select with socket"); + /* close(sockfd); */ + return -1; + } + + if (!FD_ISSET(sockfd, &rfds)) { + upsdebugx(5, "%s: received nothing from driver socket", __func__); + return -2; /* timed out, no info */ + } + + memset(buf, 0, bufsz); + ret = read(sockfd, buf, bufsz); +#else +/* + upslog_with_errno(LOG_ERR, "Support for this platform is not currently implemented"); + return -1; +*/ + DWORD bytesRead; + OVERLAPPED read_overlapped; + + /* FIXME? */ + NUT_UNUSED_VARIABLE(tv); + + memset(buf, 0, bufsz); + + /* Start a read IO so we could wait on the event associated with it */ + ReadFile(sockfd, buf, + bufsz - 1, /*-1 to be sure to have a trailling 0 */ + NULL, read_overlapped); + GetOverlappedResult(sockfd, read_overlapped, &bytesRead, FALSE); + + ret = (ssize_t)bytesRead; +#endif /* WIN32 */ + + upsdebugx(5, "%s: received %" PRIiMAX " bytes from driver socket: %s", + __func__, (intmax_t)ret, (ret > 0 ? buf : "")); + return ret; +} + +ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf) { + size_t buflen = strlen(buf); + + upsdebugx(5, "%s: write to driver socket: %s", __func__, buf); + +#ifndef WIN32 + int ret = write(sockfd, buf, buflen); + + if (ret < 0 || ret != (int)buflen) { + upslog_with_errno(LOG_ERR, "Write to socket %d failed", sockfd); + /*close(fd);*/ + /*return ERROR_FD;*/ + return -1; + } + + return ret; +#else + DWORD bytesWritten = 0; + BOOL result = FALSE; + + result = WriteFile(sockfd, buf, buflen, &bytesWritten, NULL); + if (result == 0 || bytesWritten != (DWORD)buflen) { + upslog_with_errno(LOG_ERR, "Write to handle %p failed", sockfd); + /*CloseHandle(fd);*/ + /*return ERROR_FD;*/ + return -1; + } + + return (ssize_t)bytesWritten; +#endif /* WIN32 */ +} + +ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv) { + time_t start, now; + char buf[LARGEBUF]; + + /* Avoid noise */ + if (upsdrvquery_write(sockfd, "NOBROADCAST\n") < 0) + goto socket_error; + + /* flush incoming, if any */ + time(&start); + + while (1) { + upsdrvquery_read_timeout(sockfd, tv, buf, sizeof(buf)); + time(&now); + if (difftime(now, start) > tv.tv_sec) + break; + tv.tv_sec -= difftime(now, start); + } + + /* Check that we can have a civilized dialog -- + * nope, this one is for network protocol */ +/* + if (upsdrvquery_write(sockfd, "GET TRACKING\n") < 0) + goto socket_error; + if (upsdrvquery_read_timeout(sockfd, tv, buf, sizeof(buf)) < 1) + goto socket_error; + if (strcmp(buf, "ON")) { + upslog_with_errno(LOG_ERR, "Driver does not have TRACKING support enabled"); + goto socket_error; + } +*/ + + return 1; + +socket_error: + upsdrvquery_close(sockfd); + return -1; +} + +/* UUID v4 basic implementation + * Note: 'dest' must be at least `UUID4_LEN` long */ +#define UUID4_BYTESIZE 16 +static int upsdrvquery_nut_uuid_v4(char *uuid_str) +{ + size_t i; + uint8_t nut_uuid[UUID4_BYTESIZE]; + + if (!uuid_str) + return 0; + + for (i = 0; i < UUID4_BYTESIZE; i++) + nut_uuid[i] = (uint8_t)rand() + (uint8_t)rand(); + + /* set variant and version */ + nut_uuid[6] = (nut_uuid[6] & 0x0F) | 0x40; + nut_uuid[8] = (nut_uuid[8] & 0x3F) | 0x80; + + return snprintf(uuid_str, UUID4_LEN, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + nut_uuid[0], nut_uuid[1], nut_uuid[2], nut_uuid[3], + nut_uuid[4], nut_uuid[5], nut_uuid[6], nut_uuid[7], + nut_uuid[8], nut_uuid[9], nut_uuid[10], nut_uuid[11], + nut_uuid[12], nut_uuid[13], nut_uuid[14], nut_uuid[15]); +} + +ssize_t upsdrvquery_request( + TYPE_FD sockfd, struct timeval tv, + const char *query, + char *buf, const size_t bufsz +) { + /* Assume TRACKING works; post a socket-protocol + * query to driver and return whatever it says */ + char qbuf[LARGEBUF]; + size_t qlen; + char tracking_id[UUID4_LEN]; + + if (snprintf(qbuf, sizeof(qbuf), "%s", query) < 0) + goto socket_error; + + qlen = strlen(qbuf); + while (qlen > 0 && qbuf[qlen - 1] == '\n') { + qbuf[qlen - 1] = '\0'; + qlen--; + } + + upsdrvquery_nut_uuid_v4(tracking_id); + + if (snprintf(qbuf + qlen, sizeof(qbuf) - qlen, " TRACKING %s\n", tracking_id) < 0) + goto socket_error; + + /* Post the query and wait for reply */ + if (upsdrvquery_write(sockfd, qbuf) < 0) + goto socket_error; + + if (upsdrvquery_read_timeout(sockfd, tv, buf, bufsz) < 1) + goto socket_error; + + if (!strncmp(buf, "TRACKING ", 9) && !strncmp(buf + 9, tracking_id, UUID4_LEN - 1)) { + int ret; + size_t offset = 9 + UUID4_LEN; + if (sscanf(buf + offset, " %d", &ret) < 1) { + upsdebugx(5, "%s: sscanf failed at offset %" PRIuSIZE " (char '%c')", + __func__, offset, buf[offset]); + goto socket_error; + } + upsdebugx(5, "%s: parsed out command status: %d", __func__, ret); + return ret; + } else { + upsdebugx(5, "%s: response did not have expected format", + __func__); + } + +socket_error: + upsdrvquery_close(sockfd); + return -1; +} + +ssize_t upsdrvquery_oneshot( + const char *drvname, const char *upsname, + const char *query, + char *buf, const size_t bufsz +) { + struct timeval tv; + ssize_t ret; + TYPE_FD sockfd = upsdrvquery_connect_drvname_upsname(drvname, upsname); + + if (INVALID_FD(sockfd)) + return -1; + + /* This depends on driver looping delay, polling frequency, + * being blocked on other commands, etc. Number so far is + * arbitrary and optimistic. Causes a long initial silence + * to flush incoming buffers after NOBROADCAST. + */ + tv.tv_sec = 5; + tv.tv_usec = 0; + + /* Here we have a fragile simplistic parser that + * expects one line replies to a specific command, + * so want to rule out the noise. + */ + if (upsdrvquery_prepare(sockfd, tv) < 0) + return -1; + + if ((ret = upsdrvquery_request(sockfd, tv, query, buf, bufsz)) < 0) + return -1; + + upsdrvquery_close(sockfd); + return ret; +} diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h new file mode 100644 index 0000000000..665b6d13b0 --- /dev/null +++ b/drivers/upsdrvquery.h @@ -0,0 +1,40 @@ +/* upsdrvquery.h - a single query shot over a driver socket, + tracked until a response arrives, returning + that line and closing a connection + + Copyright (C) 2023 Jim Klimov + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 NUT_UPSDRVQUERY_H_SEEN +#define NUT_UPSDRVQUERY_H_SEEN + +#include "common.h" /* TYPE_FD etc. */ +#include "timehead.h" + +TYPE_FD upsdrvquery_connect(const char *sockfn); +TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname); +void upsdrvquery_close(TYPE_FD sockfd); + +ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, const size_t bufsz); +ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf); + +ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv); +ssize_t upsdrvquery_request(TYPE_FD sockfd, struct timeval tv, const char *query, char *buf, const size_t bufsz); + +ssize_t upsdrvquery_oneshot(const char *drvname, const char *upsname, const char *query, char *buf, const size_t bufsz); + +#endif /* NUT_UPSDRVQUERY_H_SEEN */ From 8198fbd7a24dfe0143bcfab83240f6625a214c3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 22 Apr 2023 01:14:16 +0200 Subject: [PATCH 0735/1232] drivers/main.{c,h}, upsdrvctl sources and docs: add "reload-or-error" CLI handling [#1903, #1914] Handle SIGCMD_RELOAD_OR_ERROR commands to running drivers via upsdrvquery_oneshot()y --- docs/man/nutupsdrv.txt | 5 +++++ docs/man/upsdrvctl.txt | 5 +++++ drivers/main.c | 36 ++++++++++++++++++++++++++++++++++-- drivers/main.h | 2 ++ drivers/upsdrvctl.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index a999b7f214..756ccf089c 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -98,6 +98,11 @@ are: *reload*;; reread configuration files, ignoring modified settings which can not be applied "on the fly" + *reload-or-error*;; reread configuration files, ignoring but counting + changed values which require a driver restart (can not be + changed on the fly), and return a success/fail code based + on that count, so the caller can decide the fate of the + currently running driver instance *reload-or-exit*;; reread configuration files, exiting the old driver process if it encounters modified settings which can not be applied "on the fly" (so caller like diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 9e3d8b7ade..c9228fa1e3 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -126,6 +126,11 @@ are: information to their `stdout` (if attached anywhere) *reload*;; reread configuration files, ignoring modified settings which can not be applied "on the fly" + *reload-or-error*;; reread configuration files, ignoring but counting + changed values which require a driver restart (can not be + changed on the fly), and return a success/fail code based + on that count, so the caller can decide the fate of the + currently running driver instance *reload-or-exit*;; reread configuration files, exiting the old driver process if it encounters modified settings which can not be applied "on the fly" (so caller like diff --git a/drivers/main.c b/drivers/main.c index 8bedcb5fef..fd298d2510 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -26,6 +26,7 @@ #include "nut_stdint.h" #include "dstate.h" #include "attribute.h" +#include "upsdrvquery.h" #ifndef WIN32 # include @@ -203,6 +204,11 @@ static void help_msg(void) printf(" - reload: re-read configuration files, ignoring changed\n"); printf(" values which require a driver restart (can not be changed\n"); printf(" on the fly)\n"); + printf(" - reload-or-error: re-read configuration files, ignoring but\n"); + printf(" counting changed values which require a driver restart (can\n"); + printf(" not be changed on the fly), and return a success/fail code\n"); + printf(" based on that count, so the caller can decide the fate of\n"); + printf(" the currently running driver instance\n"); # ifdef SIGCMD_RELOAD_OR_RESTART printf(" - reload-or-restart: re-read configuration files (close the\n"); printf(" old driver instance device connection if needed, and have\n"); @@ -707,7 +713,7 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { # ifndef DRIVERS_MAIN_WITHOUT_MAIN if (!strcmp(cmdname, "driver.reload-or-error")) { /* sync-capable handling */ - set_reload_flag(SIGCMD_RELOAD); + set_reload_flag(SIGCMD_RELOAD_OR_ERROR); /* Returns a result code from INSTCMD enum values */ return handle_reload_flag(); } @@ -1465,6 +1471,7 @@ static void set_reload_flag(int sig) #endif case SIGCMD_RELOAD: /* SIGHUP */ + case SIGCMD_RELOAD_OR_ERROR: /* Not even a signal, but a socket protocol action */ default: /* reload what we can, log what needs a restart so skipped */ reload_flag = 1; @@ -1663,6 +1670,9 @@ int main(int argc, char **argv) if (!strncmp(optarg, "reload", strlen(optarg))) { cmd = SIGCMD_RELOAD; } else + if (!strncmp(optarg, "reload-or-error", strlen(optarg))) { + cmd = SIGCMD_RELOAD_OR_ERROR; + } else # ifdef SIGCMD_RELOAD_OR_RESTART if (!strncmp(optarg, "reload-or-restart", strlen(optarg))) { cmd = SIGCMD_RELOAD_OR_RESTART; @@ -1829,6 +1839,28 @@ int main(int argc, char **argv) setup_signals(); } + /* Handle reload-or-error over socket protocol with + * the running older driver instance */ + if (cmd == SIGCMD_RELOAD_OR_ERROR) { /* Not a signal, but a socket protocol action */ + int cmdret = -1; + char buf[LARGEBUF]; + + /* Post the query and wait for reply */ + cmdret = upsdrvquery_oneshot(progname, upsname, + "INSTCMD driver.reload-or-error\n", + buf, sizeof(buf)); + + if (cmdret < 0) { + upslog_with_errno(LOG_ERR, "Socket dialog with the other driver instance"); + } else { + /* TODO: handle buf reply contents */ + upslogx(LOG_INFO, "Request to reload-or-error returned code %d", cmdret); + } + + /* exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); */ + exit((cmdret < 0) ? 255 : cmdret); + } + /* Setup PID file to receive signals to communicate with this driver * instance once backgrounded, and to stop a competing older instance. * Or to send it a signal deliberately. @@ -1838,7 +1870,7 @@ int main(int argc, char **argv) snprintf(pidfnbuf, sizeof(pidfnbuf), "%s/%s-%s.pid", altpidpath(), progname, upsname); - if (cmd) { + if (cmd) { /* Signals */ int cmdret = -1; /* Send a signal to older copy of the driver, if any */ if (oldpid < 0) { diff --git a/drivers/main.h b/drivers/main.h index 56a08b9d56..0b33bb454e 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -130,6 +130,8 @@ void setup_signals(void); #ifndef WIN32 # define SIGCMD_RELOAD SIGHUP +/* not a signal, so negative; relies on socket protocol */ +# define SIGCMD_RELOAD_OR_ERROR -SIGCMD_RELOAD # define SIGCMD_RELOAD_OR_EXIT SIGUSR1 /* // FIXME: Implement this self-recycling in drivers (keeping the PID): # define SIGCMD_RELOAD_OR_RESTART SIGUSR2 diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index d862e7f393..1166030d3c 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -36,6 +36,7 @@ #include "attribute.h" #include "nut_stdint.h" #include "main.h" +#include "upsdrvquery.h" typedef struct { char *upsname; @@ -190,6 +191,35 @@ static void signal_driver_cmd(const ups_t *ups, char pidfn[SMALLBUF]; int ret; + if (cmd == SIGCMD_RELOAD_OR_ERROR) { + /* not a signal, use socket protocol => statefn */ + char buf[LARGEBUF]; + + if (testmode) + return; + + /* Post the query and wait for reply */ + ret = upsdrvquery_oneshot(ups->driver, ups->upsname, + "INSTCMD driver.reload-or-error\n", + buf, sizeof(buf)); + if (ret < 0) { + goto socket_error; + } else { + upslogx(LOG_INFO, "Request to reload-or-error returned code %d", ret); + if (ret != STAT_INSTCMD_HANDLED) + exec_error++; + /* TODO: Propagate "ret" to caller, eventually CLI exit-code? */ + } + + return; + +socket_error: + upslog_with_errno(LOG_ERR, "Socket dialog with the other driver instance"); + exec_error++; + return; + } + + /* Real signals */ #ifndef WIN32 upsdebugx(1, "Signalling UPS [%s]: %d (%s)", ups->upsname, cmd, strsignal(cmd)); @@ -473,6 +503,7 @@ static void set_reload_flag(const # endif case SIGCMD_RELOAD: /* SIGHUP */ + case SIGCMD_RELOAD_OR_ERROR: /* Not even a signal, but a socket protocol action */ default: /* reload what we can, log what needs a restart so skipped */ reload_flag = 1; @@ -893,6 +924,11 @@ static void help(const char *arg_progname) printf(" - reload: re-read configuration files, ignoring changed\n"); printf(" values which require a driver restart (can not be changed\n"); printf(" on the fly)\n"); + printf(" - reload-or-error: re-read configuration files, ignoring but\n"); + printf(" counting changed values which require a driver restart (can\n"); + printf(" not be changed on the fly), and return a success/fail code\n"); + printf(" based on that count, so the caller can decide the fate of\n"); + printf(" the currently running driver instance\n"); # ifdef SIGCMD_RELOAD_OR_RESTART printf(" - reload-or-restart: re-read configuration files (close the\n"); printf(" old driver instance device connection if needed, and have\n"); @@ -1134,6 +1170,9 @@ int main(int argc, char **argv) if (!strncmp(optarg, "reload", strlen(optarg))) { signal_flag = SIGCMD_RELOAD; } else + if (!strncmp(optarg, "reload-or-error", strlen(optarg))) { + signal_flag = SIGCMD_RELOAD_OR_ERROR; + } else # ifdef SIGCMD_RELOAD_OR_RESTART if (!strncmp(optarg, "reload-or-restart", strlen(optarg))) { signal_flag = SIGCMD_RELOAD_OR_RESTART; From 7155c5e2301665fb881db9775094069b25cffa40 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 13:21:20 +0200 Subject: [PATCH 0736/1232] drivers/main.c: address compiler style warning --- drivers/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index 8bedcb5fef..23324f2aaf 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1310,7 +1310,7 @@ static int handle_reload_flag(void) { } else { /* 1+ entries required a restart */ ret = STAT_INSTCMD_INVALID; - }; + } /* TODO: Callbacks in drivers to re-parse configs? * Currently this reloadability relies on either From 123be2c6d343a19f310bb4c0f95a73907cd87c7a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 13:51:10 +0200 Subject: [PATCH 0737/1232] drivers/upsdrvquery.c: upsdrvquery_connect(): copy-paste fixes for WIN32 part [#1903, #1914] --- drivers/upsdrvquery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 02d3ec7527..7bce357bc6 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -77,7 +77,7 @@ TYPE_FD upsdrvquery_connect(const char *sockfn) { return ERROR_FD; } #else - result = WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT); + BOOL result = WaitNamedPipe(sockfn, NMPWAIT_USE_DEFAULT_WAIT); if (result == FALSE) { upslog_with_errno(LOG_ERR, "WaitNamedPipe : %d\n", GetLastError()); @@ -85,7 +85,7 @@ TYPE_FD upsdrvquery_connect(const char *sockfn) { } sockfd = CreateFile( - pipename, // pipe name + sockfn, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing @@ -170,8 +170,8 @@ ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, c /* Start a read IO so we could wait on the event associated with it */ ReadFile(sockfd, buf, bufsz - 1, /*-1 to be sure to have a trailling 0 */ - NULL, read_overlapped); - GetOverlappedResult(sockfd, read_overlapped, &bytesRead, FALSE); + NULL, &read_overlapped); + GetOverlappedResult(sockfd, &read_overlapped, &bytesRead, FALSE); ret = (ssize_t)bytesRead; #endif /* WIN32 */ From a4a02caf921b2e3bdea210e3cb05ffa90cd858a8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 13:21:20 +0200 Subject: [PATCH 0738/1232] drivers/main.c: address compiler style warning --- drivers/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index fd298d2510..fa280bee91 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1316,7 +1316,7 @@ static int handle_reload_flag(void) { } else { /* 1+ entries required a restart */ ret = STAT_INSTCMD_INVALID; - }; + } /* TODO: Callbacks in drivers to re-parse configs? * Currently this reloadability relies on either From e10c705c78d6fadfec84971ac6019b7a12c9eeb9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 18:41:09 +0200 Subject: [PATCH 0739/1232] drivers/main.c: enable SIGCMD_RELOAD_OR_ERROR handling for WIN32 [#1914, #1903] --- drivers/main.c | 83 ++++++++++++++++++++++++++++++++++++++------------ drivers/main.h | 4 ++- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index fa280bee91..65093fb958 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -118,13 +118,17 @@ static int dump_data = 0; /* Store the update_count requested */ /* pre-declare some private methods used */ static void assign_debug_level(void); -#ifndef WIN32 /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ -static void set_reload_flag(int sig); -# ifndef DRIVERS_MAIN_WITHOUT_MAIN +static void set_reload_flag( +#ifndef WIN32 + int +#else + char * +#endif + sig); +#ifndef DRIVERS_MAIN_WITHOUT_MAIN /* Returns a result code from INSTCMD enum values */ static int handle_reload_flag(void); -# endif #endif /* Set in do_ups_confargs() for consumers like handle_reload_flag() */ @@ -197,18 +201,22 @@ static void help_msg(void) printf(" -q - raise log level threshold\n"); printf(" -h - display this help\n"); printf(" -k - force shutdown\n"); -# ifndef WIN32 -/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ printf(" -c - send via signal to background process\n"); printf(" Supported commands:\n"); +# ifndef WIN32 +/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ printf(" - reload: re-read configuration files, ignoring changed\n"); printf(" values which require a driver restart (can not be changed\n"); printf(" on the fly)\n"); +# endif /* WIN32 */ +/* Note: this one is beside signal-sending (goes via socket protocol): */ printf(" - reload-or-error: re-read configuration files, ignoring but\n"); printf(" counting changed values which require a driver restart (can\n"); printf(" not be changed on the fly), and return a success/fail code\n"); printf(" based on that count, so the caller can decide the fate of\n"); printf(" the currently running driver instance\n"); +# ifndef WIN32 +/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ # ifdef SIGCMD_RELOAD_OR_RESTART printf(" - reload-or-restart: re-read configuration files (close the\n"); printf(" old driver instance device connection if needed, and have\n"); @@ -709,15 +717,15 @@ int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) { return STAT_INSTCMD_HANDLED; } # endif +#endif /* WIN32 */ -# ifndef DRIVERS_MAIN_WITHOUT_MAIN +#ifndef DRIVERS_MAIN_WITHOUT_MAIN if (!strcmp(cmdname, "driver.reload-or-error")) { /* sync-capable handling */ set_reload_flag(SIGCMD_RELOAD_OR_ERROR); /* Returns a result code from INSTCMD enum values */ return handle_reload_flag(); } -# endif #endif /* By default, the driver-specific values are @@ -1452,10 +1460,16 @@ void set_exit_flag(int sig) exit_flag = sig; } +static void set_reload_flag( #ifndef WIN32 -/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ -static void set_reload_flag(int sig) + int +#else + char * +#endif + sig) { +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ switch (sig) { case SIGCMD_RELOAD_OR_EXIT: /* SIGUSR1 */ /* reload-or-exit (this driver instance may die) */ @@ -1479,8 +1493,22 @@ static void set_reload_flag(int sig) upsdebugx(1, "%s: raising reload flag due to signal %d (%s) => reload_flag=%d", __func__, sig, strsignal(sig), reload_flag); +#else + if (sig && !strcmp(sig, SIGCMD_RELOAD_OR_ERROR)) { + /* reload what we can, log what needs a restart so skipped */ + reload_flag = 1; + } else { + /* non-fatal reload as a fallback */ + reload_flag = 1; + } + + upsdebugx(1, "%s: raising reload flag due to command %s => reload_flag=%d", + __func__, sig, reload_flag); +#endif /* WIN32 */ } +#ifndef WIN32 +/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ static void handle_dstate_dump(int sig) { /* no set_dump_flag() here, make it instant */ upsdebugx(1, "%s: starting driver state dump for [%s] due to signal %d", @@ -1597,9 +1625,9 @@ int main(int argc, char **argv) /* build the driver's extra (-x) variable table */ upsdrv_makevartable(); - while ((i = getopt(argc, argv, "+a:s:kFBDd:hx:Lqr:u:g:Vi:" + while ((i = getopt(argc, argv, "+a:s:kFBDd:hx:Lqr:u:g:Vi:c:" #ifndef WIN32 - "c:P:" + "P:" #endif )) != -1) { switch (i) { @@ -1657,21 +1685,22 @@ int main(int argc, char **argv) do_lock_port = 0; do_forceshutdown = 1; break; -#ifndef WIN32 /* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ case 'c': - if (cmd != 0) { + if (cmd) { help_msg(); fatalx(EXIT_FAILURE, "Error: only one command per run can be " "sent with option -%c. Try -h for help.", i); } - if (!strncmp(optarg, "reload", strlen(optarg))) { - cmd = SIGCMD_RELOAD; - } else if (!strncmp(optarg, "reload-or-error", strlen(optarg))) { cmd = SIGCMD_RELOAD_OR_ERROR; + } +#ifndef WIN32 + else + if (!strncmp(optarg, "reload", strlen(optarg))) { + cmd = SIGCMD_RELOAD; } else # ifdef SIGCMD_RELOAD_OR_RESTART if (!strncmp(optarg, "reload-or-restart", strlen(optarg))) { @@ -1681,17 +1710,26 @@ int main(int argc, char **argv) if (!strncmp(optarg, "reload-or-exit", strlen(optarg))) { cmd = SIGCMD_RELOAD_OR_EXIT; } +#endif /* WIN32 */ /* bad command given */ - if (cmd == 0) { + if (!cmd) { help_msg(); fatalx(EXIT_FAILURE, "Error: unknown argument to option -%c. Try -h for help.", i); } +#ifndef WIN32 upsdebugx(1, "Will send signal %d (%s) for command '%s' " "to already-running driver %s-%s (if any) and exit", cmd, strsignal(cmd), optarg, progname, upsname); +#else + upsdebugx(1, "Will send request '%s' for command '%s' " + "to already-running driver %s-%s (if any) and exit", + cmd, optarg, progname, upsname); +#endif /* WIN32 */ break; + +#ifndef WIN32 /* NOTE for FIXME above: PID-signalling is non-WIN32-only for us */ case 'P': if ((oldpid = parsepid(optarg)) < 0) @@ -1838,10 +1876,16 @@ int main(int argc, char **argv) /* Setup signals to communicate with driver which is destined for a long run. */ setup_signals(); } +#endif /* WIN32 */ /* Handle reload-or-error over socket protocol with * the running older driver instance */ - if (cmd == SIGCMD_RELOAD_OR_ERROR) { /* Not a signal, but a socket protocol action */ +#ifndef WIN32 + if (cmd == SIGCMD_RELOAD_OR_ERROR) +#else + if (cmd && !strcmp(cmd, SIGCMD_RELOAD_OR_ERROR)) +#endif /* WIN32 */ + { /* Not a signal, but a socket protocol action */ int cmdret = -1; char buf[LARGEBUF]; @@ -1861,6 +1905,7 @@ int main(int argc, char **argv) exit((cmdret < 0) ? 255 : cmdret); } +#ifndef WIN32 /* Setup PID file to receive signals to communicate with this driver * instance once backgrounded, and to stop a competing older instance. * Or to send it a signal deliberately. diff --git a/drivers/main.h b/drivers/main.h index 0b33bb454e..1658ae3491 100644 --- a/drivers/main.h +++ b/drivers/main.h @@ -151,7 +151,9 @@ void setup_signals(void); # pragma warn "This OS lacks SIGURG and SIGWINCH, will not handle SIGCMD_DATA_DUMP" # endif # endif -/* FIXME: handle WIN32 builds too */ +#else +/* FIXME: handle WIN32 builds for other signals too */ +# define SIGCMD_RELOAD_OR_ERROR "driver.reload-or-error" #endif /* WIN32 */ #endif /* NUT_MAIN_H_SEEN */ From a8aeca3923e5452294c0f7496ab935c715a3b384 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 19:14:09 +0200 Subject: [PATCH 0740/1232] include/upsconf.h, common/upsconf.c, server/conf.c, server/upsd.c, drivers/main.c, drivers/upsdrvctl.c: change read_upsconf() API so it is not always fatal [#1903] --- common/upsconf.c | 20 ++++++++++++++++---- drivers/main.c | 9 +++++++-- drivers/upsdrvctl.c | 2 +- include/upsconf.h | 8 ++++++-- server/conf.c | 2 +- server/upsd.c | 2 +- 6 files changed, 32 insertions(+), 11 deletions(-) diff --git a/common/upsconf.c b/common/upsconf.c index bb7fd35108..c5716124f1 100644 --- a/common/upsconf.c +++ b/common/upsconf.c @@ -68,8 +68,12 @@ static void upsconf_err(const char *errmsg) upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg); } -/* open the ups.conf, parse it, and call back do_upsconf_args() */ -void read_upsconf(void) +/* open the ups.conf, parse it, and call back do_upsconf_args() + * returns -1 (or aborts the program) in case of errors; + * returns 1 if processing finished successfully + * See also reload_flag support in main.c for live-reload feature + */ +int read_upsconf(int fatal_errors) { char fn[SMALLBUF]; PCONF_CTX_t ctx; @@ -79,8 +83,14 @@ void read_upsconf(void) pconf_init(&ctx, upsconf_err); - if (!pconf_file_begin(&ctx, fn)) - fatalx(EXIT_FAILURE, "Can't open %s: %s", fn, ctx.errmsg); + if (!pconf_file_begin(&ctx, fn)) { + if (fatal_errors) { + fatalx(EXIT_FAILURE, "Can't open %s: %s", fn, ctx.errmsg); + } else { + upslogx(LOG_WARNING, "Can't open %s: %s", fn, ctx.errmsg); + return -1; + } + } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { @@ -95,4 +105,6 @@ void read_upsconf(void) pconf_finish(&ctx); free(ups_section); + + return 1; /* Handled OK */ } diff --git a/drivers/main.c b/drivers/main.c index 65093fb958..7f3b60f999 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1312,7 +1312,12 @@ static int handle_reload_flag(void) { * this program. */ reload_requires_restart = -1; - read_upsconf(); + /* 0 - Do not abort drivers started with '-s TMP_UPS_NAME' */ + if (read_upsconf(0) < 0) { + upsdebugx(1, "%s: read_upsconf() failed fundamentally; " + "is this driver running via ups.conf at all?", + __func__); + } upsdebugx(1, "%s: read_upsconf() for [%s] completed, restart-required verdict was: %d", __func__, upsname, reload_requires_restart); @@ -1638,7 +1643,7 @@ int main(int argc, char **argv) upsname = optarg; - read_upsconf(); + read_upsconf(1); if (!upsname_found) fatalx(EXIT_FAILURE, "Error: Section %s not found in ups.conf", diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 1166030d3c..4118483a55 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1263,7 +1263,7 @@ int main(int argc, char **argv) atexit(exit_cleanup); - read_upsconf(); + read_upsconf(1); if (argc == lastarg) { ups_t *tmp = upstable; diff --git a/include/upsconf.h b/include/upsconf.h index 4ae1b271c5..c90ed95284 100644 --- a/include/upsconf.h +++ b/include/upsconf.h @@ -32,8 +32,12 @@ extern "C" { /* callback function from read_upsconf */ void do_upsconf_args(char *upsname, char *var, char *val); -/* open the ups.conf, parse it, and call back do_upsconf_args() */ -void read_upsconf(void); +/* open the ups.conf, parse it, and call back do_upsconf_args() + * returns -1 (or aborts the program) in case of errors; + * returns 1 if processing finished successfully + * See also reload_flag support in main.c for live-reload feature + */ +int read_upsconf(int fatal_errors); #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/server/conf.c b/server/conf.c index 9528f74cac..bddd0a69ca 100644 --- a/server/conf.c +++ b/server/conf.c @@ -593,7 +593,7 @@ void conf_reload(void) } /* reload from ups.conf */ - read_upsconf(); + read_upsconf(1); /* 1 = may abort upon fundamental errors */ upsconf_add(1); /* 1 = reloading */ /* now reread upsd.conf */ diff --git a/server/upsd.c b/server/upsd.c index fa34831ab3..8c66661b62 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1903,7 +1903,7 @@ int main(int argc, char **argv) check_perms(statepath); /* handle ups.conf */ - read_upsconf(); + read_upsconf(1); /* 1 = may abort upon fundamental errors */ upsconf_add(0); /* 0 = initial */ poll_reload(); From 77dfb6ba4738e871638c9b8f5e762d4d0f072f0c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 19:23:02 +0200 Subject: [PATCH 0741/1232] ci_build.sh: suggest follow-up to poor maintainer-clean handling in autotools --- ci_build.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 6fe34cb7df..7cce57ad94 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -13,6 +13,9 @@ set -e SCRIPTDIR="`dirname "$0"`" SCRIPTDIR="`cd "$SCRIPTDIR" && pwd`" +SCRIPT_PATH="${SCRIPTDIR}/`basename $0`" +SCRIPT_ARGS=("$@") + # Quick hijack for interactive development like this: # BUILD_TYPE=fightwarn-clang ./ci_build.sh # or to quickly hit the first-found errors in a larger matrix @@ -1295,6 +1298,10 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # include all needed pre-generated files to rely less on OS facilities. if [ -s Makefile ]; then # Let initial clean-up be at default verbosity + + # Handle Ctrl+C with helpful suggestions: + trap 'echo "!!! If clean-up looped remaking the configure script for maintainer-clean, try to:"; echo " rm -f Makefile configure ; $0 $SCRIPT_ARGS"' 2 + echo "=== Starting initial clean-up (from old build products)" case "$MAKE_FLAGS $MAKE_FLAGS_CLEAN" in *V=0*) @@ -1307,6 +1314,8 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp || ${MAKE} distclean $MAKE_FLAGS_CLEAN -k \ || true echo "=== Finished initial clean-up" + + trap - 2 fi # Just prepare `configure` script; we run it at different points From b5ba8dc1473ee20302c829460648e19357b68380 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 19:37:34 +0200 Subject: [PATCH 0742/1232] drivers/upsdrvquery.c: fix upsdrvquery_read_timeout() for WIN32 builds [#1903, #1914] --- drivers/upsdrvquery.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 7bce357bc6..4bf04aba71 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -128,6 +128,11 @@ void upsdrvquery_close(TYPE_FD sockfd) { #ifndef WIN32 close(sockfd); #else + if (DisconnectNamedPipe(sockfd) == 0) { + upslogx(LOG_ERR, + "DisconnectNamedPipe error : %d", + (int)GetLastError()); + } CloseHandle(sockfd); #endif /* WIN32 */ } @@ -135,6 +140,11 @@ void upsdrvquery_close(TYPE_FD sockfd) { ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, const size_t bufsz) { ssize_t ret; + if (INVALID_FD(sockfd)) { + upslog_with_errno(LOG_ERR, "socket not initialized"); + return -1; + } + #ifndef WIN32 fd_set rfds; @@ -166,17 +176,32 @@ ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, c NUT_UNUSED_VARIABLE(tv); memset(buf, 0, bufsz); + memset(&read_overlapped, 0, sizeof(read_overlapped)); + + read_overlapped.hEvent = CreateEvent( + NULL, /* Security */ + FALSE, /* auto-reset */ + FALSE, /* initial state = non signaled */ + NULL /* no name */ + ); + + if (read_overlapped.hEvent == NULL) { + upslogx(LOG_ERR, "Can't create event for reading event log"); + return -1; + } /* Start a read IO so we could wait on the event associated with it */ ReadFile(sockfd, buf, - bufsz - 1, /*-1 to be sure to have a trailling 0 */ + bufsz - 1, /* -1 to be sure to have a trailing 0 */ NULL, &read_overlapped); - GetOverlappedResult(sockfd, &read_overlapped, &bytesRead, FALSE); + if (FALSE == GetOverlappedResult(sockfd, &read_overlapped, &bytesRead, FALSE)) + upsdebugx(6, "%s: pipe read error", __func__); ret = (ssize_t)bytesRead; #endif /* WIN32 */ - upsdebugx(5, "%s: received %" PRIiMAX " bytes from driver socket: %s", + upsdebugx(ret > 0 ? 5 : 6, + "%s: received %" PRIiMAX " bytes from driver socket: %s", __func__, (intmax_t)ret, (ret > 0 ? buf : "")); return ret; } @@ -186,6 +211,11 @@ ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf) { upsdebugx(5, "%s: write to driver socket: %s", __func__, buf); + if (INVALID_FD(sockfd)) { + upslog_with_errno(LOG_ERR, "socket not initialized"); + return -1; + } + #ifndef WIN32 int ret = write(sockfd, buf, buflen); From b4b4bae697868ee7cfe641bf7e306f96cbdcea9c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 20:42:10 +0200 Subject: [PATCH 0743/1232] docs/developers.txt: expand with a few IDE notes on Windows --- docs/developers.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/developers.txt b/docs/developers.txt index dad434b0bd..763e3498a3 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -453,6 +453,28 @@ tracing include: * Apache NetBeans 17 on Windows with MSYS2 support (as MinGW toolkit); * Visual Studio Code (VSCode) on Windows with MSYS2 support. +IDE notes on Windows +~~~~~~~~~~~~~~~~~~~~ + +When working in a native Windows environment with +link:https://www.msys2.org/[MSYS2] (providing MinGW x64 among other things), +make sure it is in the `PATH`: Control Panel => "Edit the system environment +variables" => "Environment variables..." (button) => Edit or create New "Path" +setting => Make sure `C:\msys64\mingw64\bin` is there (assuming you installed +MSYS2 into `C:\msys64` by default). Restart the IDE (if already running) for +it to acknowledge the system configuration change. + +Otherwise, NetBeans for example claims there is no shell for it to run `make`, +and fails to start the built programs due to lack of DLL files it linked +against (such as `libssl` for networked part of the codebase). + +You might still have to fiddle with DLL files built in other directories of +the NUT project, when preparing to debug certain programs, e.g. for `dummy-ups` +you may need to: +```` +:; cp ./clients/.libs/libupsclient-6.dll ./drivers/.libs/ +```` + //////// TODO: Expand on adding include and library paths to NetBeans on Windows. Plugins: unpack200 from JDK11 or older to install NB8.2 repo C/C++ plugins. From c0c95546ab745d92992918800685c1c4089422f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 21:17:16 +0200 Subject: [PATCH 0744/1232] drivers/upsdrvquery.{c,h}: refactor to pass udq_pipe_conn_t around, and complete WIN32 fixes [#1914] --- drivers/upsdrvquery.c | 275 +++++++++++++++++++++++++++--------------- drivers/upsdrvquery.h | 30 +++-- 2 files changed, 197 insertions(+), 108 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 4bf04aba71..ff65553085 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -39,8 +39,8 @@ #include "upsdrvquery.h" #include "nut_stdint.h" -TYPE_FD upsdrvquery_connect(const char *sockfn) { - TYPE_FD sockfd; +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)); /* Code borrowed from our numerous sock_connect() implems */ #ifndef WIN32 @@ -51,40 +51,44 @@ TYPE_FD upsdrvquery_connect(const char *sockfn) { sa.sun_family = AF_UNIX; snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", sockfn); - sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + conn->sockfd = socket(AF_UNIX, SOCK_STREAM, 0); - if (sockfd < 0) { + if (conn->sockfd < 0) { upslog_with_errno(LOG_ERR, "open socket"); - return ERROR_FD; + free(conn); + return NULL; } - if (connect(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + if (connect(conn->sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { upslog_with_errno(LOG_ERR, "connect to driver socket at %s", sockfn); - close(sockfd); - return ERROR_FD; + close(conn->sockfd); + free(conn); + return NULL; } - ret = fcntl(sockfd, F_GETFL, 0); + ret = fcntl(conn->sockfd, F_GETFL, 0); if (ret < 0) { upslog_with_errno(LOG_ERR, "fcntl get on driver socket %s failed", sockfn); - close(sockfd); - return ERROR_FD; + close(conn->sockfd); + free(conn); + return NULL; } - if (fcntl(sockfd, F_SETFL, ret | O_NDELAY) < 0) { + if (fcntl(conn->sockfd, F_SETFL, ret | O_NDELAY) < 0) { upslog_with_errno(LOG_ERR, "fcntl set O_NDELAY on driver socket %s failed", sockfn); - close(sockfd); - return ERROR_FD; + close(conn->sockfd); + free(conn); + return NULL; } #else BOOL result = WaitNamedPipe(sockfn, NMPWAIT_USE_DEFAULT_WAIT); if (result == FALSE) { upslog_with_errno(LOG_ERR, "WaitNamedPipe : %d\n", GetLastError()); - return ERROR_FD; + return NULL; } - sockfd = CreateFile( + conn->sockfd = CreateFile( sockfn, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, @@ -94,16 +98,45 @@ TYPE_FD upsdrvquery_connect(const char *sockfn) { FILE_FLAG_OVERLAPPED, // enable async IO NULL); // no template file - if (sockfd == INVALID_HANDLE_VALUE) { + if (conn->sockfd == INVALID_HANDLE_VALUE) { upslog_with_errno(LOG_ERR, "CreateFile : %d\n", GetLastError()); - return ERROR_FD; + free(conn); + return NULL; } + + memset(&(conn->overlapped), 0, sizeof(conn->overlapped)); + + conn->overlapped.hEvent = CreateEvent( + NULL, /* Security */ + FALSE, /* auto-reset */ + FALSE, /* initial state = non signaled */ + NULL /* no name */ + ); + + if (conn->overlapped.hEvent == NULL) { + upslogx(LOG_ERR, "Can't create event for reading event log"); + free(conn); + return NULL; + } + + memset(conn->buf, 0, sizeof(conn->buf)); + + /* Start a read IO so we could wait on the event associated with it + * Requires the persistent buffer for the connection + */ + ReadFile(conn->sockfd, conn->buf, + sizeof(conn->buf) - 1, /* -1 to be sure to have a trailing 0 */ + NULL, &conn->overlapped); + #endif /* WIN32 */ - return sockfd; + /* Just for fun: stash the name */ + if (snprintf(conn->sockfn, sizeof(conn->sockfn), "%s", sockfn) < 0) + conn->sockfn[0] = '\0'; + return conn; } -TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname) { +udq_pipe_conn_t *upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname) { char pidfn[SMALLBUF]; #ifndef WIN32 struct stat fs; @@ -112,7 +145,7 @@ TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *ups check_unix_socket_filename(pidfn); if (stat(pidfn, &fs)) { upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); - return ERROR_FD; + return NULL; } #else snprintf(pidfn, sizeof(pidfn), "\\\\.\\pipe\\%s-%s", drvname, upsname); @@ -121,26 +154,39 @@ TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *ups return upsdrvquery_connect(pidfn); } -void upsdrvquery_close(TYPE_FD sockfd) { - if (INVALID_FD(sockfd)) +void upsdrvquery_close(udq_pipe_conn_t *conn) { + if (!conn) return; #ifndef WIN32 - close(sockfd); + if (VALID_FD(conn->sockfd)) + close(conn->sockfd); #else - if (DisconnectNamedPipe(sockfd) == 0) { - upslogx(LOG_ERR, - "DisconnectNamedPipe error : %d", - (int)GetLastError()); + if (VALID_FD(conn->overlapped.hEvent)) { + CloseHandle(conn->overlapped.hEvent); + } + memset(&(conn->overlapped), 0, sizeof(conn->overlapped)); + + if (VALID_FD(conn->sockfd)) { + if (DisconnectNamedPipe(conn->sockfd) == 0) { + upslogx(LOG_ERR, + "DisconnectNamedPipe error : %d", + (int)GetLastError()); + } + CloseHandle(conn->sockfd); } - CloseHandle(sockfd); #endif /* WIN32 */ + + conn->sockfd = ERROR_FD; + memset(conn->buf, 0, sizeof(conn->buf)); + memset(conn->sockfn, 0, sizeof(conn->sockfn)); + /* caller should free the conn */ } -ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, const size_t bufsz) { +ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { ssize_t ret; - if (INVALID_FD(sockfd)) { + if (!conn || INVALID_FD(conn->sockfd)) { upslog_with_errno(LOG_ERR, "socket not initialized"); return -1; } @@ -149,81 +195,100 @@ ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, c fd_set rfds; FD_ZERO(&rfds); - FD_SET(sockfd, &rfds); + FD_SET(conn->sockfd, &rfds); - if (select(sockfd + 1, &rfds, NULL, NULL, &tv) < 0) { + if (select(conn->sockfd + 1, &rfds, NULL, NULL, &tv) < 0) { upslog_with_errno(LOG_ERR, "select with socket"); - /* close(sockfd); */ + /* upsdrvquery_close(conn); */ return -1; } - if (!FD_ISSET(sockfd, &rfds)) { + if (!FD_ISSET(conn->sockfd, &rfds)) { upsdebugx(5, "%s: received nothing from driver socket", __func__); return -2; /* timed out, no info */ } - memset(buf, 0, bufsz); - ret = read(sockfd, buf, bufsz); + memset(conn->buf, 0, sizeof(conn->buf)); + ret = read(conn->sockfd, conn->buf, sizeof(conn->buf)); #else /* upslog_with_errno(LOG_ERR, "Support for this platform is not currently implemented"); return -1; */ - DWORD bytesRead; - OVERLAPPED read_overlapped; + DWORD bytesRead = 0; + BOOL res = FALSE; + time_t start, now, presleep; - /* FIXME? */ - NUT_UNUSED_VARIABLE(tv); + time(&start); + while (res == FALSE && bytesRead == 0) { + res = GetOverlappedResult(conn->sockfd, &conn->overlapped, &bytesRead, FALSE); + if (res != FALSE || bytesRead != 0) + break; - memset(buf, 0, bufsz); - memset(&read_overlapped, 0, sizeof(read_overlapped)); + upsdebugx(6, "%s: pipe read error", __func__); - read_overlapped.hEvent = CreateEvent( - NULL, /* Security */ - FALSE, /* auto-reset */ - FALSE, /* initial state = non signaled */ - NULL /* no name */ - ); + /* Throttle down a bit */ + time(&presleep); + usleep(100); /* obsoleted in win32, so follow up below */ - if (read_overlapped.hEvent == NULL) { - upslogx(LOG_ERR, "Can't create event for reading event log"); - return -1; - } + time(&now); + if (difftime(now, presleep) < 0.1) { + /* https://stackoverflow.com/a/17283549 */ + HANDLE timer; + LARGE_INTEGER ft; + + /* SetWaitableTimer() uses 100 nanosecond intervals, + * and a negative value indicates relative time: */ + ft.QuadPart = -(10*100); /* 100 usec */ + + timer = CreateWaitableTimer(NULL, TRUE, NULL); + SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + } - /* Start a read IO so we could wait on the event associated with it */ - ReadFile(sockfd, buf, - bufsz - 1, /* -1 to be sure to have a trailing 0 */ - NULL, &read_overlapped); - if (FALSE == GetOverlappedResult(sockfd, &read_overlapped, &bytesRead, FALSE)) - upsdebugx(6, "%s: pipe read error", __func__); + time(&now); + if (difftime(now, presleep) < 0.1) + sleep(1); - ret = (ssize_t)bytesRead; + time(&now); + if (difftime(now, start) > tv.tv_sec) { + upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); + break; + } + } + + if (res != FALSE) + ret = (ssize_t)bytesRead; + else + ret = -1; #endif /* WIN32 */ upsdebugx(ret > 0 ? 5 : 6, "%s: received %" PRIiMAX " bytes from driver socket: %s", - __func__, (intmax_t)ret, (ret > 0 ? buf : "")); + __func__, (intmax_t)ret, (ret > 0 ? conn->buf : "")); + if (ret > 0 && conn->buf[0] == '\0') + upsdebug_hex(5, "payload starts with zero byte: ", + conn->buf, ((size_t)ret > sizeof(conn->buf) ? sizeof(conn->buf) : (size_t)ret)); return ret; } -ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf) { +ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { size_t buflen = strlen(buf); upsdebugx(5, "%s: write to driver socket: %s", __func__, buf); - if (INVALID_FD(sockfd)) { + if (!conn || INVALID_FD(conn->sockfd)) { upslog_with_errno(LOG_ERR, "socket not initialized"); return -1; } #ifndef WIN32 - int ret = write(sockfd, buf, buflen); + int ret = write(conn->sockfd, buf, buflen); if (ret < 0 || ret != (int)buflen) { - upslog_with_errno(LOG_ERR, "Write to socket %d failed", sockfd); - /*close(fd);*/ - /*return ERROR_FD;*/ - return -1; + upslog_with_errno(LOG_ERR, "Write to socket %d failed", conn->sockfd); + goto socket_error; } return ret; @@ -231,31 +296,32 @@ ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf) { DWORD bytesWritten = 0; BOOL result = FALSE; - result = WriteFile(sockfd, buf, buflen, &bytesWritten, NULL); + result = WriteFile(conn->sockfd, buf, buflen, &bytesWritten, NULL); if (result == 0 || bytesWritten != (DWORD)buflen) { - upslog_with_errno(LOG_ERR, "Write to handle %p failed", sockfd); - /*CloseHandle(fd);*/ - /*return ERROR_FD;*/ - return -1; + upslog_with_errno(LOG_ERR, "Write to handle %p failed", conn->sockfd); + goto socket_error; } return (ssize_t)bytesWritten; #endif /* WIN32 */ + +socket_error: + /*upsdrvquery_close(conn);*/ + return -1; } -ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv) { +ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { time_t start, now; - char buf[LARGEBUF]; /* Avoid noise */ - if (upsdrvquery_write(sockfd, "NOBROADCAST\n") < 0) + if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) goto socket_error; /* flush incoming, if any */ time(&start); while (1) { - upsdrvquery_read_timeout(sockfd, tv, buf, sizeof(buf)); + upsdrvquery_read_timeout(conn, tv); time(&now); if (difftime(now, start) > tv.tv_sec) break; @@ -265,11 +331,11 @@ ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv) { /* Check that we can have a civilized dialog -- * nope, this one is for network protocol */ /* - if (upsdrvquery_write(sockfd, "GET TRACKING\n") < 0) + if (upsdrvquery_write(conn, "GET TRACKING\n") < 0) goto socket_error; - if (upsdrvquery_read_timeout(sockfd, tv, buf, sizeof(buf)) < 1) + if (upsdrvquery_read_timeout(conn, tv) < 1) goto socket_error; - if (strcmp(buf, "ON")) { + if (strcmp(conn->buf, "ON")) { upslog_with_errno(LOG_ERR, "Driver does not have TRACKING support enabled"); goto socket_error; } @@ -278,7 +344,7 @@ ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv) { return 1; socket_error: - upsdrvquery_close(sockfd); + upsdrvquery_close(conn); return -1; } @@ -309,9 +375,8 @@ static int upsdrvquery_nut_uuid_v4(char *uuid_str) } ssize_t upsdrvquery_request( - TYPE_FD sockfd, struct timeval tv, - const char *query, - char *buf, const size_t bufsz + udq_pipe_conn_t *conn, struct timeval tv, + const char *query ) { /* Assume TRACKING works; post a socket-protocol * query to driver and return whatever it says */ @@ -334,29 +399,34 @@ ssize_t upsdrvquery_request( goto socket_error; /* Post the query and wait for reply */ - if (upsdrvquery_write(sockfd, qbuf) < 0) + if (upsdrvquery_write(conn, qbuf) < 0) goto socket_error; - if (upsdrvquery_read_timeout(sockfd, tv, buf, bufsz) < 1) + if (upsdrvquery_read_timeout(conn, tv) < 1) goto socket_error; - if (!strncmp(buf, "TRACKING ", 9) && !strncmp(buf + 9, tracking_id, UUID4_LEN - 1)) { + if (!strncmp(conn->buf, "TRACKING ", 9) + && !strncmp(conn->buf + 9, tracking_id, UUID4_LEN - 1) + ) { int ret; size_t offset = 9 + UUID4_LEN; - if (sscanf(buf + offset, " %d", &ret) < 1) { + if (sscanf(conn->buf + offset, " %d", &ret) < 1) { upsdebugx(5, "%s: sscanf failed at offset %" PRIuSIZE " (char '%c')", - __func__, offset, buf[offset]); + __func__, offset, conn->buf[offset]); goto socket_error; } - upsdebugx(5, "%s: parsed out command status: %d", __func__, ret); + upsdebugx(5, "%s: parsed out command status: %d", + __func__, ret); return ret; } else { upsdebugx(5, "%s: response did not have expected format", __func__); + /* Maybe a rogue send-to-all? */ + return -1; } socket_error: - upsdrvquery_close(sockfd); + upsdrvquery_close(conn); return -1; } @@ -367,9 +437,9 @@ ssize_t upsdrvquery_oneshot( ) { struct timeval tv; ssize_t ret; - TYPE_FD sockfd = upsdrvquery_connect_drvname_upsname(drvname, upsname); + udq_pipe_conn_t *conn = upsdrvquery_connect_drvname_upsname(drvname, upsname); - if (INVALID_FD(sockfd)) + if (!conn || INVALID_FD(conn->sockfd)) return -1; /* This depends on driver looping delay, polling frequency, @@ -384,12 +454,21 @@ ssize_t upsdrvquery_oneshot( * expects one line replies to a specific command, * so want to rule out the noise. */ - if (upsdrvquery_prepare(sockfd, tv) < 0) - return -1; + if (upsdrvquery_prepare(conn, tv) < 0) { + ret = -1; + goto finish; + } - if ((ret = upsdrvquery_request(sockfd, tv, query, buf, bufsz)) < 0) - return -1; + if ((ret = upsdrvquery_request(conn, tv, query)) < 0) { + ret = -1; + goto finish; + } - upsdrvquery_close(sockfd); + if (buf) { + snprintf(buf, bufsz, "%s", conn->buf); + } +finish: + upsdrvquery_close(conn); + free(conn); return ret; } diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h index 665b6d13b0..528e779fc3 100644 --- a/drivers/upsdrvquery.h +++ b/drivers/upsdrvquery.h @@ -25,16 +25,26 @@ #include "common.h" /* TYPE_FD etc. */ #include "timehead.h" -TYPE_FD upsdrvquery_connect(const char *sockfn); -TYPE_FD upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname); -void upsdrvquery_close(TYPE_FD sockfd); - -ssize_t upsdrvquery_read_timeout(TYPE_FD sockfd, struct timeval tv, char *buf, const size_t bufsz); -ssize_t upsdrvquery_write(TYPE_FD sockfd, const char *buf); - -ssize_t upsdrvquery_prepare(TYPE_FD sockfd, struct timeval tv); -ssize_t upsdrvquery_request(TYPE_FD sockfd, struct timeval tv, const char *query, char *buf, const size_t bufsz); - +typedef struct udq_pipe_conn_s { + TYPE_FD sockfd; +#ifdef WIN32 + OVERLAPPED overlapped; +#endif /* WIN32 */ + char buf[LARGEBUF]; + char sockfn[LARGEBUF]; +} udq_pipe_conn_t; + +udq_pipe_conn_t *upsdrvquery_connect(const char *sockfn); +udq_pipe_conn_t *upsdrvquery_connect_drvname_upsname(const char *drvname, const char *upsname); +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); + +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); + +/* if buf != NULL, last reply is copied there */ ssize_t upsdrvquery_oneshot(const char *drvname, const char *upsname, const char *query, char *buf, const size_t bufsz); #endif /* NUT_UPSDRVQUERY_H_SEEN */ From 85de34fca541072845365bc7e51a2a54050877e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 22:50:08 +0200 Subject: [PATCH 0745/1232] drivers/upsdrvctl.c: enable "-c reload-or-error" on WIN32 [#1914, #1903] --- drivers/upsdrvctl.c | 62 ++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 4118483a55..c89549e80f 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -177,9 +177,6 @@ void do_upsconf_args(char *arg_upsname, char *var, char *val) upstable = tmp; } -#ifndef WIN32 -/* TODO: implement WIN32 */ -/* handle generally signalling the UPS */ static void signal_driver_cmd(const ups_t *ups, #ifndef WIN32 int cmd @@ -188,13 +185,23 @@ static void signal_driver_cmd(const ups_t *ups, #endif ) { +#ifndef WIN32 char pidfn[SMALLBUF]; +#endif int ret; - if (cmd == SIGCMD_RELOAD_OR_ERROR) { - /* not a signal, use socket protocol => statefn */ +#ifndef WIN32 + if (cmd == SIGCMD_RELOAD_OR_ERROR) +#else + if (cmd && !strcmp(cmd, SIGCMD_RELOAD_OR_ERROR)) +#endif + { + /* not a signal, use socket protocol */ char buf[LARGEBUF]; + upsdebugx(1, "Signalling UPS [%s]: %s", + ups->upsname, "driver.reload-or-error"); + if (testmode) return; @@ -219,6 +226,9 @@ static void signal_driver_cmd(const ups_t *ups, return; } +#ifndef WIN32 +/* TODO: implement WIN32 */ +/* handle generally signalling the UPS */ /* Real signals */ #ifndef WIN32 upsdebugx(1, "Signalling UPS [%s]: %d (%s)", @@ -285,13 +295,13 @@ static void signal_driver_cmd(const ups_t *ups, upslog_with_errno(LOG_ERR, "Signalling %s failed: %d", pidfn, ret); exec_error++; } +#endif /* WIN32 */ } /* handle generally signalling the UPS with recently raised signal */ static void signal_driver(const ups_t *ups) { signal_driver_cmd(ups, signal_flag); } -#endif /* WIN32 */ /* handle sending the signal */ static void stop_driver(const ups_t *ups) @@ -476,7 +486,6 @@ static void reset_signal_flag(void) #ifndef WIN32 /* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ - static void set_reload_flag(const #ifndef WIN32 int @@ -486,8 +495,6 @@ static void set_reload_flag(const sig ) { set_signal_flag(sig); -#ifndef WIN32 -/* TODO: Equivalent for WIN32 - see SIGCMD_RELOAD in upd and upsmon */ switch (sig) { case SIGCMD_RELOAD_OR_EXIT: /* SIGUSR1 */ /* reload-or-exit (this driver instance may die) */ @@ -511,7 +518,6 @@ static void set_reload_flag(const upsdebugx(1, "%s: raising reload flag due to signal %d (%s) => reload_flag=%d", __func__, sig, strsignal(sig), reload_flag); -#endif } #endif @@ -899,9 +905,7 @@ static void help(const char *arg_progname) { printf("Starts and stops UPS drivers via ups.conf.\n\n"); printf("usage: %s [OPTIONS] (start | stop | shutdown) []\n\n", arg_progname); -#ifndef WIN32 printf("usage: %s [OPTIONS] -c []\n\n", arg_progname); -#endif printf("Common options:\n"); printf(" -h display this help\n"); @@ -914,21 +918,24 @@ static void help(const char *arg_progname) printf(" -FF driver stays foregrounded and still saves the PID file\n"); printf(" -B driver(s) stay backgrounded even if debugging is bumped\n"); -#ifndef WIN32 -/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ printf("Signalling a running driver:\n"); printf(" -c send via signal to running driver(s)\n"); printf(" supported commands:\n"); +#ifndef WIN32 +/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ printf(" - data-dump: if the driver still has STDOUT attached (maybe\n"); printf(" to log), dump its currently collected information there\n"); printf(" - reload: re-read configuration files, ignoring changed\n"); printf(" values which require a driver restart (can not be changed\n"); printf(" on the fly)\n"); +#endif /* WIN32 */ printf(" - reload-or-error: re-read configuration files, ignoring but\n"); printf(" counting changed values which require a driver restart (can\n"); printf(" not be changed on the fly), and return a success/fail code\n"); printf(" based on that count, so the caller can decide the fate of\n"); printf(" the currently running driver instance\n"); +#ifndef WIN32 +/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ # ifdef SIGCMD_RELOAD_OR_RESTART printf(" - reload-or-restart: re-read configuration files (close the\n"); printf(" old driver instance device connection if needed, and have\n"); @@ -1109,11 +1116,7 @@ int main(int argc, char **argv) UPS_VERSION); prog = argv[0]; - while ((i = getopt(argc, argv, "+htu:r:DdFBV" -#ifndef WIN32 - "c:" -#endif -)) != -1) { + while ((i = getopt(argc, argv, "+htu:r:DdFBVc:")) != -1) { switch(i) { case 'r': pt_root = optarg; @@ -1151,8 +1154,6 @@ int main(int argc, char **argv) nut_foreground_passthrough = 0; break; -#ifndef WIN32 -/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ case 'c': if (command || pt_cmd) { fatalx(EXIT_FAILURE, @@ -1161,6 +1162,12 @@ int main(int argc, char **argv) } command = &signal_driver; + if (!strncmp(optarg, "reload-or-error", strlen(optarg))) { + signal_flag = SIGCMD_RELOAD_OR_ERROR; + } +#ifndef WIN32 +/* FIXME: port event loop from upsd/upsmon to allow messaging fellow drivers in WIN32 builds */ + else if (!strncmp(optarg, "dump", strlen(optarg))) { signal_flag = SIGCMD_DATA_DUMP; } else @@ -1170,9 +1177,6 @@ int main(int argc, char **argv) if (!strncmp(optarg, "reload", strlen(optarg))) { signal_flag = SIGCMD_RELOAD; } else - if (!strncmp(optarg, "reload-or-error", strlen(optarg))) { - signal_flag = SIGCMD_RELOAD_OR_ERROR; - } else # ifdef SIGCMD_RELOAD_OR_RESTART if (!strncmp(optarg, "reload-or-restart", strlen(optarg))) { signal_flag = SIGCMD_RELOAD_OR_RESTART; @@ -1181,19 +1185,25 @@ int main(int argc, char **argv) if (!strncmp(optarg, "reload-or-exit", strlen(optarg))) { signal_flag = SIGCMD_RELOAD_OR_EXIT; } +#endif /* WIN32 */ /* bad command given */ - if (signal_flag == 0) { + if (!signal_flag) { fatalx(EXIT_FAILURE, "Error: unknown argument to option -%c. Try -h for help.", i); } pt_cmd = optarg; +#ifndef WIN32 upsdebugx(1, "Will send signal %d (%s) for command '%s' " "to already-running driver (if any) and exit", signal_flag, strsignal(signal_flag), optarg); - break; +#else + upsdebugx(1, "Will send request '%s' for command '%s' " + "to already-running driver (if any) and exit", + signal_flag, optarg); #endif /* WIN32 */ + break; case 'h': default: help(prog); From 2e6150d65627481e0d3276f57b992a8a0ce064dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 23:02:08 +0200 Subject: [PATCH 0746/1232] drivers/upsdrvquery.c: upsdrvquery_prepare(): support zeroed-out "tv" as disable of wait --- drivers/upsdrvquery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index ff65553085..3623c6b156 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -317,6 +317,9 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) goto socket_error; + if (tv.tv_sec < 1 && tv.tv_usec < 1) + return 1; + /* flush incoming, if any */ time(&start); From 5cad99c8057218c1414f12d81976e3ffe3e1a07c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 23:06:09 +0200 Subject: [PATCH 0747/1232] drivers/upsdrvquery.c: upsdrvquery_read_timeout(): support zeroed-out "tv" as disable of wait --- drivers/upsdrvquery.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 3623c6b156..bd5612d753 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -225,7 +225,11 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { if (res != FALSE || bytesRead != 0) break; - upsdebugx(6, "%s: pipe read error", __func__); + if (tv.tv_sec < 1 && tv.tv_usec < 1) { + upsdebugx(5, "%s: pipe read error (no incoming data), proceeding now", __func__); + break; + } + upsdebugx(6, "%s: pipe read error, waiting for data", __func__); /* Throttle down a bit */ time(&presleep); From 7a1a8b9027b9d2a2abe3a2bb03c6707ab3b01e24 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 23 Apr 2023 23:14:48 +0200 Subject: [PATCH 0748/1232] drivers/upsdrvquery.c: upsdrvquery_oneshot(): do not wait for NOBROADCAST to flush, we now support not-bailing on unexpected lines [#1920] --- drivers/upsdrvquery.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index bd5612d753..61b8518e46 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -451,10 +451,16 @@ ssize_t upsdrvquery_oneshot( /* This depends on driver looping delay, polling frequency, * being blocked on other commands, etc. Number so far is - * arbitrary and optimistic. Causes a long initial silence - * to flush incoming buffers after NOBROADCAST. + * arbitrary and optimistic. A non-zero setting causes a + * long initial silence to flush incoming buffers after + * the NOBROADCAST. In practice, we do not expect messages + * from dstate::send_to_all() to be a nuisance, since we + * have just connected and posted the NOBROADCAST so there + * is little chance that something appears in that short + * time. Also now we know to ignore replies that are not + * TRACKING */ - tv.tv_sec = 5; + tv.tv_sec = 0; tv.tv_usec = 0; /* Here we have a fragile simplistic parser that @@ -466,6 +472,8 @@ ssize_t upsdrvquery_oneshot( goto finish; } + tv.tv_sec = 5; + tv.tv_usec = 0; if ((ret = upsdrvquery_request(conn, tv, query)) < 0) { ret = -1; goto finish; From 57c0ecb2145c994a14736832ac5e1ce55926b97f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 00:13:49 +0200 Subject: [PATCH 0749/1232] drivers/upsdrvquery.c: rectify timeout processing precision [#1914] --- drivers/upsdrvquery.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 61b8518e46..d355e7a6e2 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -256,7 +256,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { sleep(1); time(&now); - if (difftime(now, start) > tv.tv_sec) { + if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); break; } @@ -330,9 +330,14 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { while (1) { upsdrvquery_read_timeout(conn, tv); time(&now); - if (difftime(now, start) > tv.tv_sec) + if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) break; - tv.tv_sec -= difftime(now, start); + /* Diminishing timeouts for read() */ + tv.tv_usec -= difftime(now, start); + while (tv.tv_usec < 0) { + tv.tv_sec--; + tv.tv_usec = 1000 - tv.tv_usec; + } } /* Check that we can have a civilized dialog -- From fb6d9a835a5064e614afb34a8dece73c2a36c39b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 00:14:18 +0200 Subject: [PATCH 0750/1232] drivers/upsdrvquery.c: update messages [#1914] --- drivers/upsdrvquery.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index d355e7a6e2..332916b32d 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -124,6 +124,7 @@ udq_pipe_conn_t *upsdrvquery_connect(const char *sockfn) { /* Start a read IO so we could wait on the event associated with it * Requires the persistent buffer for the connection */ + upsdebugx(6, "%s: Queue initial async read", __func__); ReadFile(conn->sockfd, conn->buf, sizeof(conn->buf) - 1, /* -1 to be sure to have a trailing 0 */ NULL, &conn->overlapped); @@ -321,12 +322,15 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) goto socket_error; - if (tv.tv_sec < 1 && tv.tv_usec < 1) + 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 */ time(&start); + upsdebugx(5, "%s: waiting for a while to flush server messages", __func__); while (1) { upsdrvquery_read_timeout(conn, tv); time(&now); @@ -353,6 +357,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } */ + upsdebugx(5, "%s: ready for tracked commands", __func__); return 1; socket_error: From 18e9475cfccbe19df3a7344bdd81b95f97940443 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 00:20:11 +0200 Subject: [PATCH 0751/1232] drivers/upsdrvquery.{c,h}: add a way to request new ReadFile() operation on WIN32 [#1914] --- drivers/upsdrvquery.c | 17 ++++++++++++++--- drivers/upsdrvquery.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 332916b32d..384e87eb85 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -128,7 +128,7 @@ udq_pipe_conn_t *upsdrvquery_connect(const char *sockfn) { ReadFile(conn->sockfd, conn->buf, sizeof(conn->buf) - 1, /* -1 to be sure to have a trailing 0 */ NULL, &conn->overlapped); - + conn->newread = 0; #endif /* WIN32 */ /* Just for fun: stash the name */ @@ -176,6 +176,7 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { } CloseHandle(conn->sockfd); } + conn->newread = 0; #endif /* WIN32 */ conn->sockfd = ERROR_FD; @@ -220,10 +221,20 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { BOOL res = FALSE; time_t start, now, presleep; + /* Is GetLastError() required to move on if pipe has more data? + * if (GetLastError() == ERROR_IO_PENDING) { + */ + if (conn->newread) { + upsdebugx(6, "%s: Restart async read", __func__); + memset(conn->buf, 0, sizeof(conn->buf)); + ReadFile(conn->sockfd, conn->buf, sizeof(conn->buf) - 1, NULL, &(conn->overlapped)); + conn->newread = 0; + } + time(&start); - while (res == FALSE && bytesRead == 0) { + while (res == FALSE /*&& bytesRead == 0*/) { res = GetOverlappedResult(conn->sockfd, &conn->overlapped, &bytesRead, FALSE); - if (res != FALSE || bytesRead != 0) + if (res != FALSE /*|| bytesRead != 0*/) break; if (tv.tv_sec < 1 && tv.tv_usec < 1) { diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h index 528e779fc3..aeeb6099cf 100644 --- a/drivers/upsdrvquery.h +++ b/drivers/upsdrvquery.h @@ -29,6 +29,7 @@ typedef struct udq_pipe_conn_s { TYPE_FD sockfd; #ifdef WIN32 OVERLAPPED overlapped; + int newread; /* Set to 1 to start a new ReadFile, forget old buf */ #endif /* WIN32 */ char buf[LARGEBUF]; char sockfn[LARGEBUF]; From 34fd46271df335e58bf2616c23af080445342c30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 00:21:49 +0200 Subject: [PATCH 0752/1232] drivers/upsdrvquery.c: upsdrvquery_request(): drop received unrecognized queued replies [#1914] --- drivers/upsdrvquery.c | 63 ++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 384e87eb85..bb9679b56c 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -411,6 +411,7 @@ ssize_t upsdrvquery_request( char qbuf[LARGEBUF]; size_t qlen; char tracking_id[UUID4_LEN]; + time_t start, now; if (snprintf(qbuf, sizeof(qbuf), "%s", query) < 0) goto socket_error; @@ -430,27 +431,51 @@ ssize_t upsdrvquery_request( if (upsdrvquery_write(conn, qbuf) < 0) goto socket_error; - if (upsdrvquery_read_timeout(conn, tv) < 1) - goto socket_error; - - if (!strncmp(conn->buf, "TRACKING ", 9) - && !strncmp(conn->buf + 9, tracking_id, UUID4_LEN - 1) - ) { - int ret; - size_t offset = 9 + UUID4_LEN; - if (sscanf(conn->buf + offset, " %d", &ret) < 1) { - upsdebugx(5, "%s: sscanf failed at offset %" PRIuSIZE " (char '%c')", - __func__, offset, conn->buf[offset]); + time(&start); + while (1) { + char *buf; + if (upsdrvquery_read_timeout(conn, tv) < 1) goto socket_error; + +#if WIN32 + /* Allow a new read to happen later */ + conn->newread = 1; +#endif + + buf = conn->buf; + while (buf && *buf) { + if (!strncmp(buf, "TRACKING ", 9) + && !strncmp(buf + 9, tracking_id, UUID4_LEN - 1) + ) { + int ret; + size_t offset = 9 + UUID4_LEN; + if (sscanf(buf + offset, " %d", &ret) < 1) { + upsdebugx(5, "%s: sscanf failed at offset %" PRIuSIZE " (char '%c')", + __func__, offset, buf[offset]); + goto socket_error; + } + upsdebugx(5, "%s: parsed out command status: %d", + __func__, ret); + return ret; + } else { + upsdebugx(5, "%s: response did not have expected format", + __func__); + /* Maybe a rogue send-to-all? */ + } + buf = strchr(buf, '\n'); + if (buf) { + upsdebugx(5, "%s: trying next line of multi-line response: %s", + __func__, buf); + buf++; /* skip EOL char */ + } + } + + time(&now); + if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { + upsdebugx(5, "%s: timed out waiting for expected response", + __func__); + return -1; } - upsdebugx(5, "%s: parsed out command status: %d", - __func__, ret); - return ret; - } else { - upsdebugx(5, "%s: response did not have expected format", - __func__); - /* Maybe a rogue send-to-all? */ - return -1; } socket_error: From 3b1ae6570942271ea875401d7d22d42c02c76e90 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 00:58:15 +0200 Subject: [PATCH 0753/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: avoid re-definition of the driver if we can just reload it [#1924] Closes: #1924 --- .../upsdrvsvcctl/nut-driver-enumerator.sh.in | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index d6b621d522..5775d4f9b5 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -990,8 +990,21 @@ nut_driver_enumerator_main() { if [ -n "$NEW_CHECKSUM" ]; then for UPSS in $NEW_CHECKSUM ; do - echo "Dropping old ${SERVICE_FRAMEWORK} service instance ${UPSS} whose section in config file has changed..." >&2 - $hook_unregisterInstance "$UPSS" + CURR_DRV="`upsconf_getDriver "$UPSS"`" || CURR_DRV="" + DO_UNREGISTER=yes + if [ -n "$CURR_DRV" ] ; then + # If reload is handled and does not complain, + # we are OK to proceed without re-defining + # and restarting the driver service instance. + "@DRVPATH@/$CURR_DRV" -a "$UPSS" -c reload-or-error >/dev/null 2>/dev/null \ + && DO_UNREGISTER=no + fi + if [ "$DO_UNREGISTER" = yes ] ; then + echo "Dropping old ${SERVICE_FRAMEWORK} service instance ${UPSS} whose section in config file has changed..." >&2 + $hook_unregisterInstance "$UPSS" + else + echo "Keeping ${SERVICE_FRAMEWORK} service instance ${UPSS} whose section in config file has changed: live reload sufficed" >&2 + fi done upslist_readSvcs "after updating for new config section checksums" fi From e98464602589d9ad8ec615fa31cb76fe2658523a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 01:20:01 +0200 Subject: [PATCH 0754/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: clarify in logged messages that we are *reloading or* restarting daemons --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index 5775d4f9b5..b237c03423 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -667,14 +667,14 @@ smf_setSavedMD5() { /usr/sbin/svcadm refresh "${TARGET_FMRI}" || return } smf_restart_upsd() { - echo "Restarting NUT data server to make sure it knows new configuration..." + echo "Reloading or restarting NUT data server to make sure it knows new configuration..." /usr/sbin/svcadm enable "nut-server" 2>/dev/null /usr/sbin/svcadm clear "nut-server" 2>/dev/null /usr/sbin/svcadm refresh "nut-server" || \ /usr/sbin/svcadm restart "nut-server" } smf_restart_drv() { - echo "Restarting NUT driver instance '$1' to make sure it knows new configuration..." + echo "Reloading or restarting NUT driver instance '$1' to make sure it knows new configuration..." /usr/sbin/svcadm enable "nut-driver:$1" 2>/dev/null /usr/sbin/svcadm clear "nut-driver:$1" 2>/dev/null /usr/sbin/svcadm refresh "nut-driver:$1" || \ @@ -789,7 +789,7 @@ systemd_restart_upsd() { *) return 0 ;; esac - echo "Restarting NUT data server to make sure it knows new configuration..." + echo "Reloading or restarting NUT data server to make sure it knows new configuration..." # Note: reload is a better way to go about this, so the # data service is not interrupted by re-initialization # of the daemon. But systemd/systemctl sometimes stalls... @@ -805,7 +805,7 @@ systemd_restart_drv() { *) return 0 ;; esac - echo "Restarting NUT driver instance '$1' to make sure it knows new configuration..." + echo "Reloading or restarting NUT driver instance '$1' to make sure it knows new configuration..." # Full restart, e.g. in case we changed the user= in configs # however let "reload" try, in case we changed something that From 904219af5375fdeb2a8b3bd652ff25a56fbf81e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 02:22:17 +0200 Subject: [PATCH 0755/1232] drivers/*: Avoid exit() and fatalx() in upsdrv_shutdown() handlers; set_exit_flag() instead [#1923] --- drivers/al175.c | 7 ++----- drivers/apcupsd-ups.c | 7 +++---- drivers/asem.c | 6 ++---- drivers/bcmxcp.c | 3 ++- drivers/blazer.c | 11 +++++------ drivers/clone-outlet.c | 5 +++++ drivers/clone.c | 7 +++---- drivers/dummy-ups.c | 7 +++---- drivers/generic_gpio_common.c | 7 +++---- drivers/generic_modbus.c | 8 ++++++-- drivers/genericups.c | 19 ++++++++++++++----- drivers/huawei-ups2000.c | 6 ++++-- drivers/isbmex.c | 7 +++++-- drivers/ivtscd.c | 8 ++++---- drivers/liebert.c | 6 ++---- drivers/macosx-ups.c | 6 ++---- drivers/main.c | 17 ++++++++++++++--- drivers/netxml-ups.c | 6 ++++-- drivers/nut-ipmipsu.c | 7 +++---- drivers/nutdrv_qx.c | 32 +++++++++++++++++++++----------- drivers/phoenixcontact_modbus.c | 7 +++---- drivers/powercom.c | 14 +++----------- drivers/powerman-pdu.c | 6 ++---- drivers/riello_ser.c | 10 +++++----- drivers/riello_usb.c | 10 +++++----- drivers/safenet.c | 4 +++- drivers/skel.c | 6 ++---- drivers/snmp-ups.c | 3 ++- drivers/socomec_jbus.c | 7 +++---- drivers/usbhid-ups.c | 3 ++- 30 files changed, 137 insertions(+), 115 deletions(-) diff --git a/drivers/al175.c b/drivers/al175.c index 9b7a655742..70588da8b3 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -1263,9 +1263,6 @@ void upsdrv_updateinfo(void) } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* TODO use TOGGLE_PRS_ONOFF for shutdown */ @@ -1276,7 +1273,8 @@ void upsdrv_shutdown(void) it doesn't respond at first if possible */ /* replace with a proper shutdown function */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); /* you may have to check the line status since the commands for toggling power are frequently different for OL vs. OB */ @@ -1286,7 +1284,6 @@ void upsdrv_shutdown(void) /* OB: the load must remain off until the power returns */ } - static int instcmd(const char *cmdname, const char *extra) { int err; diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index bf6c263c2e..1b4289e219 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -342,12 +342,11 @@ void upsdrv_updateinfo(void) poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } void upsdrv_help(void) diff --git a/drivers/asem.c b/drivers/asem.c index 7b0af43476..04abba2f76 100644 --- a/drivers/asem.c +++ b/drivers/asem.c @@ -324,9 +324,6 @@ void upsdrv_updateinfo(void) dstate_dataok(); } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ @@ -335,7 +332,8 @@ void upsdrv_shutdown(void) it doesn't respond at first if possible */ /* replace with a proper shutdown function */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); /* you may have to check the line status since the commands for toggling power are frequently different for OL vs. OB */ diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index 2c4d8a4f49..4236edc006 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -1962,7 +1962,8 @@ void upsdrv_shutdown(void) return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } diff --git a/drivers/blazer.c b/drivers/blazer.c index adc1aa2a6f..1d6209fbf2 100644 --- a/drivers/blazer.c +++ b/drivers/blazer.c @@ -849,9 +849,6 @@ void upsdrv_updateinfo(void) dstate_dataok(); } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { int retry; @@ -878,9 +875,11 @@ void upsdrv_shutdown(void) continue; } - fatalx(EXIT_SUCCESS, "Shutting down in %ld seconds", offdelay); - + upslogx(LOG_ERR, "Shutting down in %ld seconds", offdelay); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } diff --git a/drivers/clone-outlet.c b/drivers/clone-outlet.c index 762b13eb3d..16dbbeff28 100644 --- a/drivers/clone-outlet.c +++ b/drivers/clone-outlet.c @@ -479,6 +479,11 @@ void upsdrv_updateinfo(void) void upsdrv_shutdown(void) { + /* replace with a proper shutdown function */ +/* + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); + */ } diff --git a/drivers/clone.c b/drivers/clone.c index d6b55b31a5..9e9eb448f7 100644 --- a/drivers/clone.c +++ b/drivers/clone.c @@ -628,12 +628,11 @@ void upsdrv_updateinfo(void) } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 19883b916c..74fd8efe81 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -319,12 +319,11 @@ void upsdrv_updateinfo(void) } } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } static int instcmd(const char *cmdname, const char *extra) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index 6bfd8c212e..a9f3dc0881 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -477,12 +477,11 @@ void upsdrv_updateinfo(void) dstate_dataok(); } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } void upsdrv_help(void) diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index ab53f0673f..1b30b6e4ec 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -336,9 +336,13 @@ void upsdrv_shutdown(void) switch (rval) { case STAT_INSTCMD_FAILED: case STAT_INSTCMD_INVALID: - fatalx(EXIT_FAILURE, "shutdown failed"); + upslogx(LOG_ERR, "shutdown failed"); + set_exit_flag(-1); + return; case STAT_INSTCMD_UNKNOWN: - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); + return; default: break; } diff --git a/drivers/genericups.c b/drivers/genericups.c index 371a20e125..c5d574d03b 100644 --- a/drivers/genericups.c +++ b/drivers/genericups.c @@ -313,27 +313,34 @@ void upsdrv_shutdown(void) int flags, ret; if (upstype == -1) { - fatalx(EXIT_FAILURE, "No upstype set - see help text / man page!"); + upslogx(LOG_ERR, "No upstype set - see help text / man page!"); + set_exit_flag(-1); + return; } flags = upstab[upstype].line_sd; if (flags == -1) { - fatalx(EXIT_FAILURE, "No shutdown command defined for this model!"); + upslogx(LOG_ERR, "No shutdown command defined for this model!"); + set_exit_flag(-1); + return; } if (flags == TIOCM_ST) { #ifndef WIN32 #ifndef HAVE_TCSENDBREAK - fatalx(EXIT_FAILURE, "Need to send a BREAK, but don't have tcsendbreak!"); + upslogx(LOG_ERR, "Need to send a BREAK, but don't have tcsendbreak!"); + set_exit_flag(-1); + return; #endif #endif ret = tcsendbreak(upsfd, 4901); if (ret != 0) { - fatal_with_errno(EXIT_FAILURE, "tcsendbreak"); + upslog_with_errno(LOG_ERR, "tcsendbreak"); + set_exit_flag(-1); } return; @@ -346,7 +353,9 @@ void upsdrv_shutdown(void) #endif if (ret != 0) { - fatal_with_errno(EXIT_FAILURE, "ioctl TIOCMSET"); + upslog_with_errno(LOG_ERR, "ioctl TIOCMSET"); + set_exit_flag(-1); + return; } if (getval("sdtime")) { diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index 8c811c4856..b856fb6fb1 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -1801,8 +1801,10 @@ void upsdrv_shutdown(void) int r; r = instcmd("shutdown.reboot", ""); - if (r != STAT_INSTCMD_HANDLED) - fatalx(EXIT_FAILURE, "upsdrv_shutdown failed!"); + if (r != STAT_INSTCMD_HANDLED) { + upslogx(LOG_ERR, "upsdrv_shutdown failed!"); + set_exit_flag(-1); + } } diff --git a/drivers/isbmex.c b/drivers/isbmex.c index e2d4c03a54..6c3a7b6cef 100644 --- a/drivers/isbmex.c +++ b/drivers/isbmex.c @@ -357,8 +357,11 @@ void upsdrv_shutdown(void) /* * here try to do the pin 9 trick, if it does not * work, else:*/ -/* fatalx(EXIT_FAILURE, "Shutdown only supported with the Generic Driver, type 6 and special cable"); */ - /*fatalx(EXIT_FAILURE, "shutdown not supported");*/ +/* + upslogx(LOG_ERR, "Shutdown only supported with the Generic Driver, type 6 and special cable"); + //upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); +*/ int i; for(i=0;i<=5;i++) { diff --git a/drivers/ivtscd.c b/drivers/ivtscd.c index 656ca2f3f8..4f3f0a42d2 100644 --- a/drivers/ivtscd.c +++ b/drivers/ivtscd.c @@ -181,9 +181,6 @@ void upsdrv_updateinfo(void) dstate_dataok(); } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { while (1) { @@ -196,7 +193,10 @@ void upsdrv_shutdown(void) continue; } - fatalx(EXIT_SUCCESS, "Power is back!"); + /* Hmmm, why was this an exit-case before? fatalx(EXIT_SUCCESS...) */ + upslogx(LOG_ERR, "Power is back!"); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; } } diff --git a/drivers/liebert.c b/drivers/liebert.c index 65bb539700..b07e526fc0 100644 --- a/drivers/liebert.c +++ b/drivers/liebert.c @@ -41,16 +41,14 @@ upsdrv_info_t upsdrv_info = { #define ML_ONBATTERY 0x55 -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* XXX: replace with a proper shutdown function (raise DTR) */ /* worse yet: stock cables don't support shutdown at all */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } void upsdrv_initinfo(void) diff --git a/drivers/macosx-ups.c b/drivers/macosx-ups.c index 11a70b6007..9b4540b97a 100644 --- a/drivers/macosx-ups.c +++ b/drivers/macosx-ups.c @@ -262,9 +262,6 @@ void upsdrv_updateinfo(void) CFRelease(power_dictionary); } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ @@ -275,7 +272,8 @@ void upsdrv_shutdown(void) /* 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. */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); /* you may have to check the line status since the commands for toggling power are frequently different for OL vs. OB */ diff --git a/drivers/main.c b/drivers/main.c index 7f3b60f999..0a7ba32f5f 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -168,7 +168,9 @@ static void forceshutdown(void) /* the driver must not block in this function */ upsdrv_shutdown(); - exit(EXIT_SUCCESS); + + /* the driver always exits here, to not block probable ongoing shutdown */ + exit(exit_flag == -1 ? EXIT_FAILURE : EXIT_SUCCESS); } /* this function only prints the usage message; it does not call exit() */ @@ -1461,7 +1463,16 @@ static void exit_cleanup(void) void set_exit_flag(int sig) { - upsdebugx(1, "%s: raising exit flag due to signal %d", __func__, sig); + switch (exit_flag) { + case -2: + upsdebugx(1, "%s: raising exit flag due to programmatic abort: EXIT_SUCCESS", __func__); + break; + case -1: + upsdebugx(1, "%s: raising exit flag due to programmatic abort: EXIT_FAILURE", __func__); + break; + default: + upsdebugx(1, "%s: raising exit flag due to signal %d", __func__, sig); + } exit_flag = sig; } @@ -2352,6 +2363,6 @@ int main(int argc, char **argv) upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag); } - exit(EXIT_SUCCESS); + exit(exit_flag == -1 ? EXIT_FAILURE : EXIT_SUCCESS); } #endif /* DRIVERS_MAIN_WITHOUT_MAIN */ diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index a166503630..13b0a6da5c 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -451,8 +451,10 @@ void upsdrv_shutdown(void) { if (NULL != resp) object_query_destroy(resp); - if (STAT_SET_HANDLED != status) - fatalx(EXIT_FAILURE, "Shutdown failed: %d", status); + if (STAT_SET_HANDLED != status) { + upslogx(LOG_ERR, "Shutdown failed: %d", status); + set_exit_flag(-1); + } } static int instcmd(const char *cmdname, const char *extra) diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index c0dd658a4f..dedbd8ab7e 100644 --- a/drivers/nut-ipmipsu.c +++ b/drivers/nut-ipmipsu.c @@ -143,12 +143,11 @@ void upsdrv_updateinfo(void) */ } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } /* diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 61400b4cce..9c2919d6f9 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -2494,9 +2494,6 @@ int setvar(const char *varname, const char *val) } /* Try to shutdown the UPS */ -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { int retry; @@ -2511,8 +2508,11 @@ void upsdrv_shutdown(void) item = find_nut_info("ups.delay.start", 0, QX_FLAG_SKIP); /* Don't know what happened */ - if (!item) - fatalx(EXIT_FAILURE, "Unable to set start delay"); + if (!item) { + upslogx(LOG_ERR, "Unable to set start delay"); + set_exit_flag(-1); + return; + } /* Set the default value */ dstate_setinfo(item->info_type, "%s", item->dfl); @@ -2524,15 +2524,20 @@ void upsdrv_shutdown(void) val = getval(QX_VAR_ONDELAY); if (val && setvar(item->info_type, val) != STAT_SET_HANDLED) { - fatalx(EXIT_FAILURE, "Start delay '%s' out of range", val); + upslogx(LOG_ERR, "Start delay '%s' out of range", val); + set_exit_flag(-1); + return; } /* Shutdown delay */ item = find_nut_info("ups.delay.shutdown", 0, QX_FLAG_SKIP); /* Don't know what happened */ - if (!item) - fatalx(EXIT_FAILURE, "Unable to set shutdown delay"); + if (!item) { + upslogx(LOG_ERR, "Unable to set shutdown delay"); + set_exit_flag(-1); + return; + } /* Set the default value */ dstate_setinfo(item->info_type, "%s", item->dfl); @@ -2544,7 +2549,9 @@ void upsdrv_shutdown(void) val = getval(QX_VAR_OFFDELAY); if (val && setvar(item->info_type, val) != STAT_SET_HANDLED) { - fatalx(EXIT_FAILURE, "Shutdown delay '%s' out of range", val); + upslogx(LOG_ERR, "Shutdown delay '%s' out of range", val); + set_exit_flag(-1); + return; } /* Stop pending shutdowns */ @@ -2583,11 +2590,14 @@ void upsdrv_shutdown(void) } - fatalx(EXIT_SUCCESS, "Shutting down in %s seconds", + upslogx(LOG_ERR, "Shutting down in %s seconds", dstate_getinfo("ups.delay.shutdown")); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } #ifdef QX_USB diff --git a/drivers/phoenixcontact_modbus.c b/drivers/phoenixcontact_modbus.c index fb4b24e3b3..9bfee7d916 100644 --- a/drivers/phoenixcontact_modbus.c +++ b/drivers/phoenixcontact_modbus.c @@ -131,12 +131,11 @@ void upsdrv_updateinfo(void) } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } void upsdrv_help(void) diff --git a/drivers/powercom.c b/drivers/powercom.c index c3a45a1463..7f9819a9ec 100644 --- a/drivers/powercom.c +++ b/drivers/powercom.c @@ -289,9 +289,6 @@ static unsigned int OPTImodels[] = {0,0,0,575,0,0,0,0,0,0,0,0,0,0,0,0}; * local used functions */ -static void shutdown_halt(void) - __attribute__((noreturn)); - static void shutdown_halt(void) { ser_send_char (upsfd, (unsigned char)SHUTDOWN); @@ -299,11 +296,9 @@ static void shutdown_halt(void) ser_send_char (upsfd, types[type].shutdown_arguments.delay[0]); ser_send_char (upsfd, types[type].shutdown_arguments.delay[1]); upslogx(LOG_INFO, "Shutdown (stayoff) initiated."); - exit (0); -} -static void shutdown_ret(void) - __attribute__((noreturn)); + set_exit_flag(-2); /* EXIT_SUCCESS */ +} static void shutdown_ret(void) { @@ -314,7 +309,7 @@ static void shutdown_ret(void) ser_send_char (upsfd, types[type].shutdown_arguments.delay[1]); upslogx(LOG_INFO, "Shutdown (return) initiated."); - exit (0); + set_exit_flag(-2); /* EXIT_SUCCESS */ } /* registered instant commands */ @@ -844,9 +839,6 @@ void upsdrv_updateinfo(void) } /* shutdown UPS */ -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* power down the attached load immediately */ diff --git a/drivers/powerman-pdu.c b/drivers/powerman-pdu.c index d1e55bfcdd..46a432b21a 100644 --- a/drivers/powerman-pdu.c +++ b/drivers/powerman-pdu.c @@ -133,13 +133,11 @@ void upsdrv_initinfo(void) /* FIXME: no need for setvar (ex for outlet.n.delay.*)!? */ } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* FIXME: shutdown all outlets? */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); /* OL: this must power cycle the load if possible */ /* OB: the load must remain off until the power returns */ diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index 72ef709ae0..cd3b8a997e 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -966,9 +966,6 @@ void upsdrv_updateinfo(void) */ } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ @@ -998,10 +995,13 @@ void upsdrv_shutdown(void) continue; } - fatalx(EXIT_SUCCESS, "Shutting down"); + upslogx(LOG_ERR, "Shutting down"); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 36c451e208..f6047129b9 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -1007,9 +1007,6 @@ void upsdrv_initinfo(void) upsh.instcmd = riello_instcmd; } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ @@ -1038,10 +1035,13 @@ void upsdrv_shutdown(void) continue; } - fatalx(EXIT_SUCCESS, "Shutting down"); + upslogx(LOG_ERR, "Shutting down"); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } void upsdrv_updateinfo(void) diff --git a/drivers/safenet.c b/drivers/safenet.c index 2715db85b6..df5da33d89 100644 --- a/drivers/safenet.c +++ b/drivers/safenet.c @@ -434,7 +434,9 @@ void upsdrv_shutdown(void) continue; } - fatalx(EXIT_FAILURE, "SafeNet protocol compatible UPS not found on %s", device_path); + upslogx(LOG_ERR, "SafeNet protocol compatible UPS not found on %s", device_path); + set_exit_flag(-1); + return; } /* diff --git a/drivers/skel.c b/drivers/skel.c index f6d4cb39f7..e79d5d8ea8 100644 --- a/drivers/skel.c +++ b/drivers/skel.c @@ -94,9 +94,6 @@ void upsdrv_updateinfo(void) */ } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ @@ -105,7 +102,8 @@ void upsdrv_shutdown(void) it doesn't respond at first if possible */ /* replace with a proper shutdown function */ - fatalx(EXIT_FAILURE, "shutdown not supported"); + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); /* you may have to check the line status since the commands for toggling power are frequently different for OL vs. OB */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 9ebc4816d0..efb9d53f8e 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -370,7 +370,8 @@ void upsdrv_shutdown(void) return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } void upsdrv_help(void) diff --git a/drivers/socomec_jbus.c b/drivers/socomec_jbus.c index fd1f865310..8eabe35844 100644 --- a/drivers/socomec_jbus.c +++ b/drivers/socomec_jbus.c @@ -426,12 +426,11 @@ void upsdrv_updateinfo(void) return; } -void upsdrv_shutdown(void) - __attribute__((noreturn)); - void upsdrv_shutdown(void) { - fatalx(EXIT_FAILURE, "shutdown not supported"); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); } void upsdrv_help(void) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index f6ba14c968..38d9c35eea 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -759,7 +759,8 @@ void upsdrv_shutdown(void) return; } - fatalx(EXIT_FAILURE, "Shutdown failed!"); + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); } void upsdrv_help(void) From 721af15d0555e1aa6f22b9c4b5b581830964c6db Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 02:30:40 +0200 Subject: [PATCH 0756/1232] drivers/main.c: try to do_forceshutdown via socket protocol with a running driver first [#1923] Closes: #1923 --- drivers/main.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 0a7ba32f5f..d7a938ba6f 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1894,6 +1894,44 @@ int main(int argc, char **argv) } #endif /* WIN32 */ + if (do_forceshutdown) { + /* First try to handle this over socket protocol + * with the running older driver instance (if any); + * if this does not succeed, fall through to legacy + * approach (kill sibling if needed, recapture device, + * command it...) + */ + int cmdret = -1; + + /* Post the query and wait for reply */ + cmdret = upsdrvquery_oneshot(progname, upsname, + "SET driver.flag.allow_killpower 1\n", + NULL, 0); + + if (cmdret >= 0) { + cmdret = upsdrvquery_oneshot(progname, upsname, + "INSTCMD driver.killpower\n", + NULL, 0); + + if (cmdret < 0) { + upsdebugx(1, "Socket dialog with the other driver instance: %s", strerror(errno)); + } else { + upslogx(LOG_INFO, "Request to killpower via running driver returned code %d", cmdret); + if (cmdret == 0) + /* Note: many drivers would abort with + * "shutdown not supported" at this + * point... we would too, but later + * and at a higher time/processing cost. + */ + exit (EXIT_SUCCESS); + /* else fall through to legacy handling */ + } + } else { + upsdebugx(1, "Socket dialog with the other driver instance: %s", + strerror(errno)); + } + } + /* Handle reload-or-error over socket protocol with * the running older driver instance */ #ifndef WIN32 From b852cc98fc3a043dfac7e65d1f1f2673dc7180d1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 02:43:59 +0200 Subject: [PATCH 0757/1232] drivers/dummy-ups.c: handle "-x port=./path" or "C:\somepath" (WIN32) [#1921] Closes: #1921 --- drivers/dummy-ups.c | 54 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 74fd8efe81..d71f7911ba 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -227,29 +227,40 @@ void upsdrv_updateinfo(void) struct stat fs; char fn[SMALLBUF]; - if (device_path[0] == '/') + if (device_path[0] == '/' +#ifdef WIN32 + || device_path[1] == ':' /* "C:\..." */ +#endif + ) snprintf(fn, sizeof(fn), "%s", device_path); - else + else if (device_path[0] == '.') { + /* "./" or "../" e.g. via CLI */ + getcwd(fn, sizeof(fn)); + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); /* Determine if file modification timestamp has changed * since last use (so we would want to re-read it) */ #ifndef WIN32 /* Either successful stat is OK to fill the "fs" struct */ - if (0 != fstat (upsfd, &fs) && 0 != stat (fn, &fs)) { + if (0 != fstat (upsfd, &fs) && 0 != stat (fn, &fs)) #else /* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA? * https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228 */ - if (0 != stat (fn, &fs)) { + if (0 != stat (fn, &fs)) #endif + { upsdebugx(2, "Can't open %s currently", fn); /* retry ASAP until we get a file */ memset(&datafile_stat, 0, sizeof(struct stat)); next_update = 1; } else { if (datafile_stat.st_mtime != fs.st_mtime) { - upsdebugx(2, "upsdrv_updateinfo: input file was already read once to the end, but changed later - re-reading"); + upsdebugx(2, + "upsdrv_updateinfo: input file was already read once " + "to the end, but changed later - re-reading: %s", fn); /* updated file => retry ASAP */ next_update = 1; datafile_stat = fs; @@ -461,22 +472,33 @@ void upsdrv_initups(void) #endif } - if (device_path[0] == '/') + if (device_path[0] == '/' +#ifdef WIN32 + || device_path[1] == ':' /* "C:\..." */ +#endif + ) snprintf(fn, sizeof(fn), "%s", device_path); - else + else if (device_path[0] == '.') { + /* "./" or "../" e.g. via CLI */ + getcwd(fn, sizeof(fn)); + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); /* Update file modification timestamp (and other data) */ #ifndef WIN32 /* Either successful stat is OK to fill the "datafile_stat" struct */ - if (0 != fstat (upsfd, &datafile_stat) && 0 != stat (device_path, &datafile_stat)) { + if (0 != fstat (upsfd, &datafile_stat) && 0 != stat (device_path, &datafile_stat)) #else /* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA? * https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228 */ - if (0 != stat (device_path, &datafile_stat)) { + if (0 != stat (device_path, &datafile_stat)) #endif - upsdebugx(2, "Can't open %s currently", device_path); + { + upsdebugx(2, "Can't open %s (%s) currently", device_path, fn); + } else { + upsdebugx(2, "Located %s for device simulation data: %s", device_path, fn); } } } @@ -693,9 +715,17 @@ static int parse_data_file(TYPE_FD arg_upsfd) { ctx = (PCONF_CTX_t *)xmalloc(sizeof(PCONF_CTX_t)); - if (device_path[0] == '/') + if (device_path[0] == '/' +#ifdef WIN32 + || device_path[1] == ':' /* "C:\..." */ +#endif + ) snprintf(fn, sizeof(fn), "%s", device_path); - else + else if (device_path[0] == '.') { + /* "./" or "../" e.g. via CLI */ + getcwd(fn, sizeof(fn)); + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); pconf_init(ctx, upsconf_err); From 981b4394bde2c74130219574f574ee2cf258a4e8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 03:08:53 +0200 Subject: [PATCH 0758/1232] drivers/upsdrvquery.c: typo fix --- drivers/upsdrvquery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index bb9679b56c..62c47575b6 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -437,7 +437,7 @@ ssize_t upsdrvquery_request( if (upsdrvquery_read_timeout(conn, tv) < 1) goto socket_error; -#if WIN32 +#ifdef WIN32 /* Allow a new read to happen later */ conn->newread = 1; #endif From bd7afc7356da1c1c7eaddac212cc6e328a1be339 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 03:35:44 +0200 Subject: [PATCH 0759/1232] NEWS: Update about reload ability [#1903, #1914, #1924] and new use of driver.killpower instcmd [#1917, #1923] --- NEWS | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 3c5aeb010f..e6d8c677c6 100644 --- a/NEWS +++ b/NEWS @@ -300,22 +300,25 @@ https://github.com/networkupstools/nut/milestone/8 + and a `driver.killpower` instant command (for safety, must be unlocked by `driver.flag.allow_killpower` protocol setting or `allow_killpower` - configuration flag) [#1917] + configuration flag), which is now the first choice for `driver -k` + operations [#1917, #1923] - Implemented basic support for `ups.conf` reloading in NUT drivers, - currently limited to `SIGHUP` handling and with a goal of changing - `debug_min` setting for a running driver. As currently implemented, - would not fully benefit the drivers on systems managed by real-time - `nut-driver-enumerator` (it does not track what exactly changed), but - it is possible to change/add/remove `debug_min` in the global section - and the drivers get only reloaded and not restarted. Reload signals - should be reasonably supported with `upsdrvctl`. Relevant CLI options - for `-c CMD` handing were added to drivers and `upsdrvctl` [#1903] + with a `driver.reload-with-error` instant command (more commands and + signal handling may be available depending on platform), with a goal + of changing inconsequential settings like `debug_min` for a running + driver. This can also benefit the drivers on systems managed by real-time + `nut-driver-enumerator` and for simpler changes the drivers get only + reloaded and not redefined and restarted. Reload signals should also + be reasonably supported with `upsdrvctl` tool. Relevant CLI options + for `-c CMD` handing were added to drivers and `upsdrvctl`, although + their availability may vary between operating systems [#1903, #1914, #1924] - Drivers should now accept `SIGURG` (or `SIGWINCH` on systems that lack - the former) to dump their current state information and move on. - Such report goes to `stdout` of the driver process (may be disconnected - when background mode is used) -- this can help with troubleshooting [#1907] + the former) on POSIX platforms to dump their current state information + and move on. Such report goes to `stdout` of the driver process (may + be disconnected when background mode is used) -- this can help with + troubleshooting [#1907] - Recipes and `main.c` code were enhanced to produce a `libdummy_mockdrv.la` helper library during build (not intended to be installed nor distributed), From 6e2eb4b2b2e9df8b5dff777134d01079cc5f1516 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 03:42:15 +0200 Subject: [PATCH 0760/1232] drivers/dummy-ups.c: do not ignore return of getcwd() [#1921] --- drivers/dummy-ups.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index d71f7911ba..c20295bd68 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -235,8 +235,10 @@ void upsdrv_updateinfo(void) snprintf(fn, sizeof(fn), "%s", device_path); else if (device_path[0] == '.') { /* "./" or "../" e.g. via CLI */ - getcwd(fn, sizeof(fn)); - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + if (getcwd(fn, sizeof(fn))) { + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else + snprintf(fn, sizeof(fn), "%s", device_path); } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); @@ -480,8 +482,10 @@ void upsdrv_initups(void) snprintf(fn, sizeof(fn), "%s", device_path); else if (device_path[0] == '.') { /* "./" or "../" e.g. via CLI */ - getcwd(fn, sizeof(fn)); - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + if (getcwd(fn, sizeof(fn))) { + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else + snprintf(fn, sizeof(fn), "%s", device_path); } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); @@ -723,8 +727,10 @@ static int parse_data_file(TYPE_FD arg_upsfd) snprintf(fn, sizeof(fn), "%s", device_path); else if (device_path[0] == '.') { /* "./" or "../" e.g. via CLI */ - getcwd(fn, sizeof(fn)); - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + if (getcwd(fn, sizeof(fn))) { + snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); + } else + snprintf(fn, sizeof(fn), "%s", device_path); } else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); From cec742797272ab693c8a80253b333707fe3395be Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 19:08:55 +0200 Subject: [PATCH 0761/1232] docs/new-drivers.txt: upsdrv_shutdown() must not exit() anymore [#1923] --- docs/new-drivers.txt | 7 +++++++ docs/nut.dict | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index d24504dd54..1174d71789 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -159,6 +159,13 @@ fails. If the UPS does not shut down the load, then the user is vulnerable to a race if the power comes back on during the shutdown process. +This method should not directly `exit()` the driver program (neither +should it call `fatalx()` nor `fatal_with_errno()` methods). It can +`upslogx(LOG_ERR, ...)` or `upslog_with_errno(LOG_ERR, ...)`, and then +`set_exit_flag(N)` if required (`-1` for `EXIT_FAILURE` and `-2` for +`EXIT_SUCCESS` which would be handled in the standard driver loop or +`forceshutdown()` method of `main.c`). + Data types ---------- diff --git a/docs/nut.dict b/docs/nut.dict index 262f339248..07d64f2757 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3123 utf-8 +personal_ws-1.1 en 3124 utf-8 AAS ABI ACFAIL @@ -1910,6 +1910,7 @@ firmwares flts fmt footnoteref +forceshutdown forcessl formatconfig formatparam From 66524d4095871b3e2d83238529313b63b69c40f1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 19:28:20 +0200 Subject: [PATCH 0762/1232] drivers/upsdrvquery.c: upsdrvquery_request(): report how long we wait (and support indefinite waits) [#1914] --- drivers/upsdrvquery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 62c47575b6..b3588418da 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -431,6 +431,20 @@ ssize_t upsdrvquery_request( if (upsdrvquery_write(conn, qbuf) < 0) goto socket_error; + if (tv.tv_sec < 1 && tv.tv_usec < 1) { + upsdebugx(1, "%s: will wait indefinitely for response to %s", + __func__, query); + } else { + while (tv.tv_usec >= 1000) { + tv.tv_usec -= 1000; + tv.tv_sec++; + } + upsdebugx(5, "%s: will wait up to %" PRIiMAX + ".%03" PRIiMAX " sec for response to %s", + __func__, (intmax_t)tv.tv_sec, + (intmax_t)tv.tv_usec, query); + } + time(&start); while (1) { char *buf; @@ -471,6 +485,13 @@ ssize_t upsdrvquery_request( } time(&now); + if (tv.tv_sec < 1 && tv.tv_usec < 1) { + if ( ((long)(difftime(now, start))) % 60 == 0 ) + upsdebugx(5, "%s: waiting indefinitely for response to %s", __func__, query); + sleep(1); + continue; + } + if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); From 73acd0f37c832ab2e4ff3b5acfd87edd7128aabc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 19:29:25 +0200 Subject: [PATCH 0763/1232] drivers/upsdrvquery.c: upsdrvquery_oneshot(): support optional caller-provided timeouts [#1929] --- drivers/upsdrvquery.c | 12 +++++++++--- drivers/upsdrvquery.h | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index b3588418da..1cc54c079a 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -507,7 +507,8 @@ ssize_t upsdrvquery_request( ssize_t upsdrvquery_oneshot( const char *drvname, const char *upsname, const char *query, - char *buf, const size_t bufsz + char *buf, const size_t bufsz, + struct timeval *ptv ) { struct timeval tv; ssize_t ret; @@ -539,8 +540,13 @@ ssize_t upsdrvquery_oneshot( goto finish; } - tv.tv_sec = 5; - tv.tv_usec = 0; + if (ptv) { + tv.tv_sec = ptv->tv_sec; + tv.tv_usec = ptv->tv_usec; + } else { + tv.tv_sec = 5; + tv.tv_usec = 0; + } if ((ret = upsdrvquery_request(conn, tv, query)) < 0) { ret = -1; goto finish; diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h index aeeb6099cf..6a7b879d6b 100644 --- a/drivers/upsdrvquery.h +++ b/drivers/upsdrvquery.h @@ -46,6 +46,6 @@ 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); /* if buf != NULL, last reply is copied there */ -ssize_t upsdrvquery_oneshot(const char *drvname, const char *upsname, const char *query, char *buf, const size_t bufsz); +ssize_t upsdrvquery_oneshot(const char *drvname, const char *upsname, const char *query, char *buf, const size_t bufsz, struct timeval *tv); #endif /* NUT_UPSDRVQUERY_H_SEEN */ From ed2b959bb2de7c484d92ec6fb01dfb3133389ae9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 19:30:09 +0200 Subject: [PATCH 0764/1232] drivers/upsdrvctl.c, drivers.main.c: use upsdrvquery_oneshot() caller-provided timeouts [#1929] Closes: #1929 --- drivers/main.c | 17 ++++++++++++++--- drivers/upsdrvctl.c | 6 +++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 63a6ee1174..320f38bc56 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1912,16 +1912,23 @@ int main(int argc, char **argv) * command it...) */ int cmdret = -1; + struct timeval tv; /* Post the query and wait for reply */ + /* FIXME: coordinate with pollfreq? */ + tv.tv_sec = 15; + tv.tv_usec = 0; cmdret = upsdrvquery_oneshot(progname, upsname, "SET driver.flag.allow_killpower 1\n", - NULL, 0); + NULL, 0, &tv); if (cmdret >= 0) { + /* FIXME: somehow mark drivers expected to loop infinitely? */ + tv.tv_sec = -1; + tv.tv_usec = -1; cmdret = upsdrvquery_oneshot(progname, upsname, "INSTCMD driver.killpower\n", - NULL, 0); + NULL, 0, &tv); if (cmdret < 0) { upsdebugx(1, "Socket dialog with the other driver instance: %s", strerror(errno)); @@ -1952,11 +1959,15 @@ int main(int argc, char **argv) { /* Not a signal, but a socket protocol action */ int cmdret = -1; char buf[LARGEBUF]; + struct timeval tv; /* Post the query and wait for reply */ + /* FIXME: coordinate with pollfreq? */ + tv.tv_sec = 15; + tv.tv_usec = 0; cmdret = upsdrvquery_oneshot(progname, upsname, "INSTCMD driver.reload-or-error\n", - buf, sizeof(buf)); + buf, sizeof(buf), &tv); if (cmdret < 0) { upslog_with_errno(LOG_ERR, "Socket dialog with the other driver instance"); diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index c89549e80f..c403d939fe 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -198,6 +198,7 @@ static void signal_driver_cmd(const ups_t *ups, { /* not a signal, use socket protocol */ char buf[LARGEBUF]; + struct timeval tv; upsdebugx(1, "Signalling UPS [%s]: %s", ups->upsname, "driver.reload-or-error"); @@ -206,9 +207,12 @@ static void signal_driver_cmd(const ups_t *ups, return; /* Post the query and wait for reply */ + /* FIXME: coordinate with pollfreq? */ + tv.tv_sec = 15; + tv.tv_usec = 0; ret = upsdrvquery_oneshot(ups->driver, ups->upsname, "INSTCMD driver.reload-or-error\n", - buf, sizeof(buf)); + buf, sizeof(buf), &tv); if (ret < 0) { goto socket_error; } else { From 29fa2f6d343fc0782aa6a24b98bf89636030463f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 19:34:13 +0200 Subject: [PATCH 0765/1232] drivers/upsdrvctl.c: when starting to send_all_drivers() or send_one_driver(), reset exec_error to 0 [#1927] --- drivers/upsdrvctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index c403d939fe..3c07ceb4c1 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1007,6 +1007,7 @@ static void send_one_driver(void (*command_func)(const ups_t *), const char *arg if (!ups) fatalx(EXIT_FAILURE, "Error: no UPS definitions found in ups.conf!\n"); + exec_error = 0; while (ups) { if (!strcmp(ups->upsname, arg_upsname)) { command_func(ups); @@ -1028,6 +1029,7 @@ static void send_all_drivers(void (*command_func)(const ups_t *)) if (!upstable) fatalx(EXIT_FAILURE, "Error: no UPS definitions found in ups.conf"); + exec_error = 0; if (command_func != &shutdown_driver) { ups = upstable; From 06f4734d313faa259b5a99b569636f6c560c09ad Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 24 Apr 2023 23:18:39 +0200 Subject: [PATCH 0766/1232] docs/man/upsset.conf.txt, conf/upsset.conf.sample: document CGI securing syntax for modern Apache Thanks to Phil Stracchino for suggestions: https://alioth-lists.debian.net/pipermail/nut-upsuser/2023-April/013262.html --- conf/upsset.conf.sample | 16 +++++++++++++++- docs/man/upsset.conf.txt | 15 ++++++++++++++- docs/nut.dict | 5 ++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/conf/upsset.conf.sample b/conf/upsset.conf.sample index 921a20aa52..3bb4850573 100644 --- a/conf/upsset.conf.sample +++ b/conf/upsset.conf.sample @@ -15,7 +15,7 @@ # your web server, then you should *not* run this program. # # For Apache, the .htaccess file can be used in the directory with the -# programs. You'll need something like this: +# programs. You'll need something like this for older versions: # # # deny from all @@ -25,6 +25,20 @@ # You will probably have to set "AllowOverride Limit" for this directory in # your server-level configuration file as well. # +# Modern Apache enjoys a more detailed syntax, like this: +# +# ScriptAlias /upsstats.cgi /usr/share/nut/cgi/upsstats.cgi +# ScriptAlias /upsset.cgi /usr/share/nut/cgi/upsset.cgi +# +# +# Options +Includes +ExecCGI +# AllowOverride Limit +# +# Require local +# Require ip aa.bb.cc.dd/nn +# +# +# # If this doesn't make sense, then stop reading and leave this program alone. # # Assuming you have all this done (and it works), then you may uncomment diff --git a/docs/man/upsset.conf.txt b/docs/man/upsset.conf.txt index 02cd996714..6fab07a7e3 100644 --- a/docs/man/upsset.conf.txt +++ b/docs/man/upsset.conf.txt @@ -32,7 +32,7 @@ secure it. On Apache, you can use the .htaccess file or put the directives in your httpd.conf. It looks something like this, assuming the .htaccess -method: +method for older Apache releases: deny from all @@ -42,6 +42,19 @@ method: You will probably have to set "AllowOverride Limit" for this directory in your server-level configuration file as well. +Modern Apache enjoys a more detailed syntax, like this: + + ScriptAlias /upsstats.cgi /usr/share/nut/cgi/upsstats.cgi + ScriptAlias /upsset.cgi /usr/share/nut/cgi/upsset.cgi + + Options +Includes +ExecCGI + AllowOverride Limit + + Require local + Require ip aa.bb.cc.dd/nn + + + If this doesn't make sense, then stop reading and leave this program alone. It's not something you absolutely need to have anyway. diff --git a/docs/nut.dict b/docs/nut.dict index 262f339248..20f6a0aedc 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3123 utf-8 +personal_ws-1.1 en 3126 utf-8 AAS ABI ACFAIL @@ -341,6 +341,7 @@ Erikson Eriksson Evgeny Exar +ExecCGI FD FEMEA FFF @@ -1038,6 +1039,7 @@ Rene René Repotec's Repoteck +RequireAny Richthof Rickard Ridgway @@ -1142,6 +1144,7 @@ Schmier Schoch Schonefeld Schroder +ScriptAlias Sekury Selinger SendEnv From a0fd8861ce25ff639c53cae5ebf818c981e189b9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 20:18:35 +0200 Subject: [PATCH 0767/1232] Makefile.am: add a way to "make sockdebug" regardless of target platform --- Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.am b/Makefile.am index 429befdfa1..1b632c97f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -212,6 +212,9 @@ cppcheck: @echo "CPPCHECK analysis not available since 'cppcheck' was not found." endif !HAVE_CPPCHECK +sockdebug: + cd $(builddir)/server && $(MAKE) $(AM_MAKEFLAGS) sockdebug$(EXEEXT) + # ---------------------------------------------------------------------- # Automatically generate the ChangeLog from Git logs: MAINTAINERCLEANFILES += ChangeLog From b6f4ed3387daf5875f61eae265d31e3cd0ef119f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 20:45:42 +0200 Subject: [PATCH 0768/1232] Introduce docs/man/sockdebug.txt --- docs/man/Makefile.am | 7 +++++ docs/man/sockdebug.txt | 71 ++++++++++++++++++++++++++++++++++++++++++ docs/nut.dict | 8 ++++- 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 docs/man/sockdebug.txt diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index ac12283aea..0441fdf015 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -190,6 +190,7 @@ SRC_DEV_PAGES = \ nutscan_init.txt \ nutscan_get_serial_ports_list.txt \ libupsclient-config.txt \ + sockdebug.txt \ skel.txt if WITH_MANS @@ -314,10 +315,14 @@ upscli_sendline_timeout.3: upscli_sendline.3 MAN1_DEV_PAGES = \ libupsclient-config.1 + +MAN8_DEV_PAGES = \ + sockdebug.8 endif if WITH_DEV man3_MANS = $(MAN3_DEV_PAGES) +man8_MANS = $(MAN8_DEV_PAGES) if !WITH_PKG_CONFIG man1_MANS = $(MAN1_DEV_PAGES) @@ -371,6 +376,7 @@ HTML_DEV_MANS = \ nutscan_get_serial_ports_list.html \ nutscan_init.html \ libupsclient-config.html \ + sockdebug.html \ skel.html @@ -693,6 +699,7 @@ MAN_MANS += \ $(MAN8_CGI_PAGES) \ $(MAN1_DEV_PAGES) \ $(MAN3_DEV_PAGES) \ + $(MAN8_DEV_PAGES) \ $(MAN_SERIAL_PAGES) \ $(MAN_SNMP_PAGES) \ $(MAN_USB_LIBUSB_PAGES) \ diff --git a/docs/man/sockdebug.txt b/docs/man/sockdebug.txt new file mode 100644 index 0000000000..5f84837fc3 --- /dev/null +++ b/docs/man/sockdebug.txt @@ -0,0 +1,71 @@ +SOCKDEBUG(8) +============ + +NAME +---- + +sockdebug - simple developer/troubleshooting aid utility to communicate +with a NUT driver using the socket protocol + +SYNOPSIS +-------- + +POSIX system builds: +*sockdebug* statefilepath + +For example: + sockdebug /var/state/ups/dummy-ups-UPS1 + +WIN32 builds: +*sockdebug* pipename + +For example: + sockdebug.exe dummy-ups-UPS1 + +DESCRIPTION +----------- + +*sockdebug* is a tool built when NUT `configure --with-dev` is enabled. +It may alternatively be built by calling `make sockdebug` in the root +of the build workspace. Actual source files used depend on the platform. + +It is used to connect to a NUT driver using the socket protocol on an +Unix socket or Windows pipe, similarly to how the linkman:upsd[8] data +server talks to the locally running drivers in order to represent them +on the network further using the common NUT protocol of the Network UPS +Tools project, or how driver programs can communicate to their already +running instances to implement commands like live `reload-or-error`. + +This tool allows a developer or troubleshooter to watch the broadcast +updates emitted by the driver, as well as to issue unicast commands and +receive replies (during an interactive investigation session, you may +want to command `NOBROADCAST` first). + +For more details see the `docs/sock-protocol.txt` file in NUT sources. + +OPTIONS +------- + +*libupsclient-config* accepts the following options: + +*socketname*:: +Either a full path (in POSIX builds) or the base name of device socket/pipe, +comprised of a `drivername-devicename` tuple, e.g. `dummy-ups-UPS1` for a +`dummy-ups` driver instance handling an `UPS1` device configuration (which +in turn may originate in the `ups.conf` file or be dynamically constructed +for tests by calling the driver program with a `-s TMP` option). + +AUTHORS +------- + +This manual page was written by Jim Klimov . + +SEE ALSO +-------- + +linkman:upsd[8] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ + +The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ diff --git a/docs/nut.dict b/docs/nut.dict index eda6c51c46..703c81e6a3 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3127 utf-8 +personal_ws-1.1 en 3133 utf-8 AAS ABI ACFAIL @@ -1775,6 +1775,7 @@ devctl devd devel deviceGetClients +devicename devscan dfl dhcp @@ -2322,6 +2323,7 @@ mozilla msec msi msvcrt +msys multi multicommands multilib @@ -2506,6 +2508,7 @@ pigz pijuice pinout pinouts +pipename pkg pkgconf pkgconfig @@ -2749,6 +2752,7 @@ snprintfcat snr socat sockdebug +socketname socomec solaris solis @@ -2774,6 +2778,7 @@ stan startIP startdelay startup +statefilepath statepath stayoff stderr @@ -2935,6 +2940,7 @@ unconfigured undefine undervoltage unescaped +unicast uninstall uninterruptible uniq From 6c1287312a0f6d07b4211a63021eb7b380de72ad Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:00:33 +0200 Subject: [PATCH 0769/1232] server/Makefile.am, NEWS, UPGRADING: install sockdebug if configured --with-dev --- NEWS | 4 ++++ UPGRADING | 4 ++++ server/Makefile.am | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e6d8c677c6..4708266258 100644 --- a/NEWS +++ b/NEWS @@ -277,6 +277,10 @@ https://github.com/networkupstools/nut/milestone/8 to toggle whether they want to receive `send_to_all()` updates from a driver, or only answers to requests they send [#1914] + - Added support for `make sockdebug` for easier developer access to the tool; + also if `configure --with-dev` is in effect, it would now be installed to + the configured `libexec` location. A man page was also added. [#1936] + - Numerous daemons (`upsd`, `upsmon`, drivers, `upsdrvctl`, `upssched`) which accepted `-D` option for debug setting previously, now can also honour a `NUT_DEBUG_LEVEL=NUM` environment variable if no `-D` arguments diff --git a/UPGRADING b/UPGRADING index a6a09315af..ca424d6916 100644 --- a/UPGRADING +++ b/UPGRADING @@ -65,6 +65,10 @@ Changes from 2.8.0 to 2.8.1 the packaging recipes may use NUT source-code facilities and package just symlinks as relevant for each distro separately [#1462, #1504] +- Added support for `make sockdebug` for easier developer access to the tool; + also if `configure --with-dev` is in effect, it would now be installed to + the configured `libexec` location. A man page was also added. [#1936] + - NUT software-only drivers (dummy-ups, clone, clone-outlet) separated from serial drivers in respective Makefile and configure script options - this may impact packaging decisions on some distributions going forward [#1446] diff --git a/server/Makefile.am b/server/Makefile.am index 7e0b5d1074..fb18ff484b 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -38,11 +38,17 @@ else !HAVE_WINDOWS sockdebug_SOURCES = sockdebug.c endif !HAVE_WINDOWS +if WITH_DEV +# Have it installed properly +libexec_PROGRAMS = sockdebug +endif + dummy: MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, # the root Makefile.am takes care of that! -#clean-local: +clean-local: + $(AM_V_at)rm -rf $(EXTRA_PROGRAMS) # $(AM_V_at)rm -rf $(builddir)/.deps From 50f4d652f638971290a24cafa6345897ee62544b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:13:31 +0200 Subject: [PATCH 0770/1232] server/sockdebug.c: fall back to dflt_statepath() when not using a full path to socket --- server/sockdebug.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/server/sockdebug.c b/server/sockdebug.c index d8dbd6535c..8ec699319b 100644 --- a/server/sockdebug.c +++ b/server/sockdebug.c @@ -1,6 +1,8 @@ /* sockdebug.c - Network UPS Tools driver-server socket debugger + Source variant for POSIX-compliant builds of NUT Copyright (C) 2003 Russell Kroll + Copyright (C) 2023 Jim Klimov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -64,6 +66,12 @@ static int socket_connect(const char *sockfn) ret = connect(fd, (struct sockaddr *) &sa, sizeof(sa)); + if (ret < 0 && !strchr(sockfn, '/')) { + snprintf(sa.sun_path, sizeof(sa.sun_path), "%s/%s", + dflt_statepath(), sockfn); + ret = connect(fd, (struct sockaddr *) &sa, sizeof(sa)); + } + if (ret < 0) { perror("connect"); exit(EXIT_FAILURE); @@ -128,8 +136,11 @@ int main(int argc, char **argv) || (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) ) { fprintf(stderr, "usage: %s \n", prog); - fprintf(stderr, " %s /var/state/ups/apcsmart-ttyS1.newsock\n", + fprintf(stderr, " %s /var/state/ups/apcsmart-ttyS1\n", + argv[0]); + fprintf(stderr, " or %s apcsmart-ttyS1\n", argv[0]); + fprintf(stderr, " for socket files placed in the standard location\n"); exit(EXIT_SUCCESS); } From a27b25c6e8914555e2bb4a39d0104cac96d16052 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:21:19 +0200 Subject: [PATCH 0771/1232] drivers/upsdrvquery.c: whitespace fixes --- drivers/upsdrvquery.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 1cc54c079a..a89223f819 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -350,8 +350,8 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { /* Diminishing timeouts for read() */ tv.tv_usec -= difftime(now, start); while (tv.tv_usec < 0) { - tv.tv_sec--; - tv.tv_usec = 1000 - tv.tv_usec; + tv.tv_sec--; + tv.tv_usec = 1000 - tv.tv_usec; } } @@ -440,7 +440,7 @@ ssize_t upsdrvquery_request( tv.tv_sec++; } upsdebugx(5, "%s: will wait up to %" PRIiMAX - ".%03" PRIiMAX " sec for response to %s", + ".%03" PRIiMAX " sec for response to %s", __func__, (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec, query); } @@ -521,12 +521,12 @@ ssize_t upsdrvquery_oneshot( * being blocked on other commands, etc. Number so far is * arbitrary and optimistic. A non-zero setting causes a * long initial silence to flush incoming buffers after - * the NOBROADCAST. In practice, we do not expect messages - * from dstate::send_to_all() to be a nuisance, since we - * have just connected and posted the NOBROADCAST so there - * is little chance that something appears in that short - * time. Also now we know to ignore replies that are not - * TRACKING + * the NOBROADCAST. In practice, we do not expect messages + * from dstate::send_to_all() to be a nuisance, since we + * have just connected and posted the NOBROADCAST so there + * is little chance that something appears in that short + * time. Also now we know to ignore replies that are not + * TRACKING */ tv.tv_sec = 0; tv.tv_usec = 0; From 3795c3ca37cb7b0e6436d7559cde0a491ccc2d77 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:28:06 +0200 Subject: [PATCH 0772/1232] drivers/upsdrvquery.c: use PING after NOBROADCAST to minimize delays while playing safe [#1928] --- drivers/upsdrvquery.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index a89223f819..9ba94f291b 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -341,12 +341,43 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { /* flush incoming, if any */ time(&start); + if (upsdrvquery_write(conn, "PING\n") < 0) + goto socket_error; + upsdebugx(5, "%s: waiting for a while to flush server messages", __func__); while (1) { + char *buf; upsdrvquery_read_timeout(conn, tv); time(&now); - if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) + if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { + upsdebugx(5, "%s: requested timeout expired", __func__); break; + } + + /* Await a PONG for quick confirmation of achieved quietness + * (should only happen after the driver handled NOBROADCAST) + */ +#ifdef WIN32 + /* Allow a new read to happen later */ + conn->newread = 1; +#endif + + buf = conn->buf; + while (buf && *buf) { + if (!strncmp(buf, "PONG\n", 5)) { + upsdebugx(5, "%s: got expected PONG", __func__); + break; + } + buf = strchr(buf, '\n'); + if (buf) { +/* + upsdebugx(5, "%s: trying next line of multi-line response: %s", + __func__, buf); +*/ + buf++; /* skip EOL char */ + } + } + /* Diminishing timeouts for read() */ tv.tv_usec -= difftime(now, start); while (tv.tv_usec < 0) { From 8f07bee807c2a0749f3f77385203f64a42dc0310 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:31:42 +0200 Subject: [PATCH 0773/1232] docs/sock-protocol.txt: update for unified ability to "make sockdebug" and no longer required fully-qualified path to socket in POSIX builds --- docs/sock-protocol.txt | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index 8adadd57d2..bd440cbc18 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -20,15 +20,12 @@ to the socket (you may want to enable `NOBROADCAST` mode soon), e.g. socat - UNIX-CONNECT:/var/state/ups/dummy-ups-UPS1 For more insight, NUT provides an optional tool of its own (not built -by default), the `sockdebug`: +by default): the `sockdebug` which is built when `configure --with-dev` +is in effect, or can be requested from the root directory of the build +workspace: - # POSIX - (cd server && make sockdebug) && \ - ./server/sockdebug /var/state/ups/dummy-ups-UPS1 - - # WIN32 - (cd server && make sockdebug.exe) && \ - ./server/sockdebug.exe dummy-ups-UPS1 + make sockdebug && \ + ./server/sockdebug dummy-ups-UPS1 Formatting ---------- From 1e7019e55563d02440cbe540fbb199bd1add8542 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:34:42 +0200 Subject: [PATCH 0774/1232] docs/man/sockdebug.txt: update for unified ability to "make sockdebug" and no longer required fully-qualified path to socket in POSIX builds --- docs/man/sockdebug.txt | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/man/sockdebug.txt b/docs/man/sockdebug.txt index 5f84837fc3..8ccdd3a042 100644 --- a/docs/man/sockdebug.txt +++ b/docs/man/sockdebug.txt @@ -10,18 +10,14 @@ with a NUT driver using the socket protocol SYNOPSIS -------- -POSIX system builds: -*sockdebug* statefilepath +*sockdebug* socketname -For example: - sockdebug /var/state/ups/dummy-ups-UPS1 - -WIN32 builds: -*sockdebug* pipename - -For example: +For example (WIN32 and POSIX builds): sockdebug.exe dummy-ups-UPS1 +For example (POSIX-compliant systems using an alternate state path): + sockdebug /var/state/ups/dummy-ups-UPS1 + DESCRIPTION ----------- @@ -49,11 +45,12 @@ OPTIONS *libupsclient-config* accepts the following options: *socketname*:: -Either a full path (in POSIX builds) or the base name of device socket/pipe, -comprised of a `drivername-devicename` tuple, e.g. `dummy-ups-UPS1` for a -`dummy-ups` driver instance handling an `UPS1` device configuration (which -in turn may originate in the `ups.conf` file or be dynamically constructed -for tests by calling the driver program with a `-s TMP` option). +Either a full path (in POSIX builds) or the base name of device socket/pipe +(on all platforms), comprised of a `drivername-devicename` tuple, e.g. some +`dummy-ups-UPS1` for a `dummy-ups` driver instance handling an `UPS1` device +configuration (which in turn may originate in the `ups.conf` file or be +dynamically constructed for tests by calling the driver program with a +`-s TMP` CLI option). AUTHORS ------- From ac96e4936e78d1acaa34d657fbe4cb7be68b172f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 21:43:21 +0200 Subject: [PATCH 0775/1232] drivers/upsdrvquery.c: enable a timeout and PING/PONG when preparing the connection --- drivers/upsdrvquery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 9ba94f291b..2516e74e89 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -559,7 +559,7 @@ ssize_t upsdrvquery_oneshot( * time. Also now we know to ignore replies that are not * TRACKING */ - tv.tv_sec = 0; + tv.tv_sec = 1; tv.tv_usec = 0; /* Here we have a fragile simplistic parser that From af003a66126e5d22015b3f36b886e34dd31d6716 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 22:02:43 +0200 Subject: [PATCH 0776/1232] drivers/upsdrvquery.c: upsdrvquery_prepare(): fix finishing quickly after a PONG --- drivers/upsdrvquery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 2516e74e89..2f2a386df6 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -366,7 +366,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__); - break; + goto finish; } buf = strchr(buf, '\n'); if (buf) { @@ -399,6 +399,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } */ +finish: upsdebugx(5, "%s: ready for tracked commands", __func__); return 1; From 9f105c82590d7322d74f924e6b085a3c18f3f490 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 10 May 2023 22:06:58 +0200 Subject: [PATCH 0777/1232] drivers/upsdrvquery.c: fix whitespace --- drivers/upsdrvquery.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 2f2a386df6..57cff43f2a 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -250,17 +250,17 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { time(&now); if (difftime(now, presleep) < 0.1) { /* https://stackoverflow.com/a/17283549 */ - HANDLE timer; - LARGE_INTEGER ft; + HANDLE timer; + LARGE_INTEGER ft; /* SetWaitableTimer() uses 100 nanosecond intervals, * and a negative value indicates relative time: */ ft.QuadPart = -(10*100); /* 100 usec */ - timer = CreateWaitableTimer(NULL, TRUE, NULL); - SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); + timer = CreateWaitableTimer(NULL, TRUE, NULL); + SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); } time(&now); From 61686c77cf85527df68d32c23dcab11c6e3db484 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 02:22:05 +0200 Subject: [PATCH 0778/1232] server/sockdebug.c: address clang warnings --- server/sockdebug.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/server/sockdebug.c b/server/sockdebug.c index 8ec699319b..b1c3addbdf 100644 --- a/server/sockdebug.c +++ b/server/sockdebug.c @@ -32,7 +32,7 @@ #include "parseconf.h" #include "nut_stdint.h" - PCONF_CTX_t sock_ctx; +static PCONF_CTX_t sock_ctx; static void sock_arg(size_t numarg, char **arg) { @@ -186,6 +186,20 @@ int main(int argc, char **argv) } } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunreachable-code" +#endif +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunreachable-code" +#endif /* NOTREACHED */ exit(EXIT_FAILURE); +#ifdef __clang__ +# pragma clang diagnostic pop +#endif +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) +# pragma GCC diagnostic pop +#endif } From c017323e9a58bc7d29cbe731353b00116c1da366 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 02:26:57 +0200 Subject: [PATCH 0779/1232] drivers/upsdrvquery.c: fix whitespace --- drivers/upsdrvquery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 57cff43f2a..15c454357b 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -218,7 +218,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { return -1; */ DWORD bytesRead = 0; - BOOL res = FALSE; + BOOL res = FALSE; time_t start, now, presleep; /* Is GetLastError() required to move on if pipe has more data? @@ -543,8 +543,8 @@ ssize_t upsdrvquery_oneshot( struct timeval *ptv ) { struct timeval tv; - ssize_t ret; - udq_pipe_conn_t *conn = upsdrvquery_connect_drvname_upsname(drvname, upsname); + ssize_t ret; + udq_pipe_conn_t *conn = upsdrvquery_connect_drvname_upsname(drvname, upsname); if (!conn || INVALID_FD(conn->sockfd)) return -1; From e353ca5a7542526c560adabe828a56c531633969 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 02:30:52 +0200 Subject: [PATCH 0780/1232] drivers/upsdrvquery.c: upsdrvquery_read_timeout(): accept shorter delays, Windows does not guarantee a minimum sleep it seems --- drivers/upsdrvquery.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 15c454357b..b832e058de 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -248,7 +248,8 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { usleep(100); /* obsoleted in win32, so follow up below */ time(&now); - if (difftime(now, presleep) < 0.1) { + /* accept shorter delays, Windows does not guarantee a minimum sleep it seems */ + if (difftime(now, presleep) < 0.05) { /* https://stackoverflow.com/a/17283549 */ HANDLE timer; LARGE_INTEGER ft; @@ -264,7 +265,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { } time(&now); - if (difftime(now, presleep) < 0.1) + if (difftime(now, presleep) < 0.05) sleep(1); time(&now); From fb763b306f5f88fa3a10e300c626a71cbfec1e2c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 02:46:55 +0200 Subject: [PATCH 0781/1232] drivers/upsdrvquery.c: fix multipliers around tv_usec (10e6 not 10e3) --- drivers/upsdrvquery.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index b832e058de..4a7964678d 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -269,7 +269,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { sleep(1); time(&now); - if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { + if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); break; } @@ -350,7 +350,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { char *buf; upsdrvquery_read_timeout(conn, tv); time(&now); - if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { + if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: requested timeout expired", __func__); break; } @@ -383,7 +383,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { tv.tv_usec -= difftime(now, start); while (tv.tv_usec < 0) { tv.tv_sec--; - tv.tv_usec = 1000 - tv.tv_usec; + tv.tv_usec = 1000000 - tv.tv_usec; } } @@ -468,12 +468,12 @@ ssize_t upsdrvquery_request( upsdebugx(1, "%s: will wait indefinitely for response to %s", __func__, query); } else { - while (tv.tv_usec >= 1000) { - tv.tv_usec -= 1000; + while (tv.tv_usec >= 1000000) { + tv.tv_usec -= 1000000; tv.tv_sec++; } upsdebugx(5, "%s: will wait up to %" PRIiMAX - ".%03" PRIiMAX " sec for response to %s", + ".%06" PRIiMAX " sec for response to %s", __func__, (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec, query); } @@ -525,7 +525,7 @@ ssize_t upsdrvquery_request( continue; } - if (difftime(now, start) > tv.tv_sec + 0.001 * tv.tv_usec) { + if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); return -1; From e9587ccc441da8ebc335d1e562b467caffc51760 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 03:19:55 +0200 Subject: [PATCH 0782/1232] common/common.c, include/common.h: introduce a difftimeval() --- common/common.c | 30 ++++++++++++++++++++++++++++++ include/common.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/common/common.c b/common/common.c index 38383e401b..391b993751 100644 --- a/common/common.c +++ b/common/common.c @@ -659,6 +659,36 @@ const char *xbasename(const char *file) return p + 1; } +/* Based on https://www.gnu.org/software/libc/manual/html_node/Calculating-Elapsed-Time.html + * modified for a syntax similar to difftime() + */ +double difftimeval(struct timeval x, struct timeval y) +{ + struct timeval result; + double d; + + /* Perform the carry for the later subtraction by updating y. */ + if (x.tv_usec < y.tv_usec) { + intmax_t nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; + y.tv_usec -= 1000000 * nsec; + y.tv_sec += nsec; + } + + if (x.tv_usec - y.tv_usec > 1000000) { + intmax_t nsec = (x.tv_usec - y.tv_usec) / 1000000; + y.tv_usec += 1000000 * nsec; + y.tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + * tv_usec is certainly positive. */ + result.tv_sec = x.tv_sec - y.tv_sec; + result.tv_usec = x.tv_usec - y.tv_usec; + + d = 0.000001 * result.tv_usec + result.tv_sec; + return d; +} + #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC /* From https://github.com/systemd/systemd/blob/main/src/basic/time-util.c * and https://github.com/systemd/systemd/blob/main/src/basic/time-util.h diff --git a/include/common.h b/include/common.h index c402f5677f..27524f3acc 100644 --- a/include/common.h +++ b/include/common.h @@ -407,6 +407,9 @@ char * getfullpath(char * relative_path); #define PATH_LIB "\\..\\lib" #endif /* WIN32*/ +/* Return a difference of two timevals as a floating-point number */ +double difftimeval(struct timeval x, struct timeval y); + #ifndef HAVE_USLEEP /* int __cdecl usleep(unsigned int useconds); */ /* Note: if we'd need to define an useconds_t for obscure systems, From 17423d48f8e2107cf1f04e4db6103571fb2f00ec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 03:24:34 +0200 Subject: [PATCH 0783/1232] drivers/upsdrvquery.c: use difftimeval() and better-precision struct timeval --- drivers/upsdrvquery.c | 45 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 4a7964678d..0a2118fc20 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -219,7 +219,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { */ DWORD bytesRead = 0; BOOL res = FALSE; - time_t start, now, presleep; + struct timeval start, now, presleep; /* Is GetLastError() required to move on if pipe has more data? * if (GetLastError() == ERROR_IO_PENDING) { @@ -231,7 +231,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { conn->newread = 0; } - time(&start); + gettimeofday(&start, NULL); while (res == FALSE /*&& bytesRead == 0*/) { res = GetOverlappedResult(conn->sockfd, &conn->overlapped, &bytesRead, FALSE); if (res != FALSE /*|| bytesRead != 0*/) @@ -244,12 +244,19 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { upsdebugx(6, "%s: pipe read error, waiting for data", __func__); /* Throttle down a bit */ - time(&presleep); + gettimeofday(&presleep, NULL); usleep(100); /* obsoleted in win32, so follow up below */ - time(&now); + gettimeofday(&now, NULL); + upsdebugx(6, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld", + __func__, presleep.tv_sec, presleep.tv_usec, + now.tv_sec, now.tv_usec, + difftime(now.tv_sec, presleep.tv_sec), + (long)(now.tv_usec - presleep.tv_usec) + ); + /* accept shorter delays, Windows does not guarantee a minimum sleep it seems */ - if (difftime(now, presleep) < 0.05) { + if (difftimeval(now, presleep) < 0.05) { /* https://stackoverflow.com/a/17283549 */ HANDLE timer; LARGE_INTEGER ft; @@ -264,12 +271,12 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { CloseHandle(timer); } - time(&now); - if (difftime(now, presleep) < 0.05) + gettimeofday(&now, NULL); + if (difftimeval(now, presleep) < 0.05) sleep(1); - time(&now); - if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + gettimeofday(&now, NULL); + if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); break; } @@ -328,7 +335,7 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { } ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { - time_t start, now; + struct timeval start, now; /* Avoid noise */ if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) @@ -340,7 +347,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } /* flush incoming, if any */ - time(&start); + gettimeofday(&start, NULL); if (upsdrvquery_write(conn, "PING\n") < 0) goto socket_error; @@ -349,8 +356,8 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { while (1) { char *buf; upsdrvquery_read_timeout(conn, tv); - time(&now); - if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + gettimeofday(&now, NULL); + if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: requested timeout expired", __func__); break; } @@ -380,7 +387,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } /* Diminishing timeouts for read() */ - tv.tv_usec -= difftime(now, start); + tv.tv_usec -= difftimeval(now, start); while (tv.tv_usec < 0) { tv.tv_sec--; tv.tv_usec = 1000000 - tv.tv_usec; @@ -444,7 +451,7 @@ ssize_t upsdrvquery_request( char qbuf[LARGEBUF]; size_t qlen; char tracking_id[UUID4_LEN]; - time_t start, now; + struct timeval start, now; if (snprintf(qbuf, sizeof(qbuf), "%s", query) < 0) goto socket_error; @@ -478,7 +485,7 @@ ssize_t upsdrvquery_request( (intmax_t)tv.tv_usec, query); } - time(&start); + gettimeofday(&start, NULL); while (1) { char *buf; if (upsdrvquery_read_timeout(conn, tv) < 1) @@ -517,15 +524,15 @@ ssize_t upsdrvquery_request( } } - time(&now); + gettimeofday(&now, NULL); if (tv.tv_sec < 1 && tv.tv_usec < 1) { - if ( ((long)(difftime(now, start))) % 60 == 0 ) + if ( ((long)(difftimeval(now, start))) % 60 == 0 ) upsdebugx(5, "%s: waiting indefinitely for response to %s", __func__, query); sleep(1); continue; } - if (difftime(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); return -1; From 36f6c279a9f0675b1a10ac708818d7c0257201d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 03:34:01 +0200 Subject: [PATCH 0784/1232] drivers/upsdrvquery.c: upsdrvquery_read_timeout(): more tracing of time tracking --- drivers/upsdrvquery.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 0a2118fc20..0a0c88be47 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -248,11 +248,12 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { usleep(100); /* obsoleted in win32, so follow up below */ gettimeofday(&now, NULL); - upsdebugx(6, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld", + upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", __func__, presleep.tv_sec, presleep.tv_usec, now.tv_sec, now.tv_usec, difftime(now.tv_sec, presleep.tv_sec), - (long)(now.tv_usec - presleep.tv_usec) + (long)(now.tv_usec - presleep.tv_usec), + difftimeval(now, presleep) ); /* accept shorter delays, Windows does not guarantee a minimum sleep it seems */ @@ -272,10 +273,24 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { } gettimeofday(&now, NULL); + upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", + __func__, presleep.tv_sec, presleep.tv_usec, + now.tv_sec, now.tv_usec, + difftime(now.tv_sec, presleep.tv_sec), + (long)(now.tv_usec - presleep.tv_usec), + difftimeval(now, presleep) + ); if (difftimeval(now, presleep) < 0.05) sleep(1); gettimeofday(&now, NULL); + upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", + __func__, presleep.tv_sec, presleep.tv_usec, + now.tv_sec, now.tv_usec, + difftime(now.tv_sec, presleep.tv_sec), + (long)(now.tv_usec - presleep.tv_usec), + difftimeval(now, presleep) + ); if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); break; From d053712b94020eeadd878f3aadb20b0d305c35ea Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 03:38:49 +0200 Subject: [PATCH 0785/1232] drivers/upsdrvquery.c: upsdrvquery_oneshot(): bump the sleep for upsdrvquery_read_timeout() PING/PONG --- drivers/upsdrvquery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 0a0c88be47..2e4a5ecf8c 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -583,7 +583,7 @@ ssize_t upsdrvquery_oneshot( * time. Also now we know to ignore replies that are not * TRACKING */ - tv.tv_sec = 1; + tv.tv_sec = 3; tv.tv_usec = 0; /* Here we have a fragile simplistic parser that From 716dcca8e18402566d8dda318b8b8185833006ee Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:19:17 +0200 Subject: [PATCH 0786/1232] drivers/upsdrvquery.c: upsdrvquery_prepare(): fix time subtraction --- drivers/upsdrvquery.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 2e4a5ecf8c..bd0b3d2dae 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -405,7 +405,11 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { tv.tv_usec -= difftimeval(now, start); while (tv.tv_usec < 0) { tv.tv_sec--; - tv.tv_usec = 1000000 - tv.tv_usec; + tv.tv_usec = 1000000 + tv.tv_usec; // Note it is negative + } + if (tv.tv_sec <= 0 && tv.tv_usec <= 0) { + upsdebugx(5, "%s: requested timeout expired", __func__); + break; } } From 4f0067053afbbbf59a71711f9e65af30ec2cfc08 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:25:29 +0200 Subject: [PATCH 0787/1232] drivers/upsdrvquery.c: clearer parentheses and markup --- drivers/upsdrvquery.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index bd0b3d2dae..085a4b0c68 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -280,6 +280,8 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { (long)(now.tv_usec - presleep.tv_usec), difftimeval(now, presleep) ); + + /* If nothing was honored, doze off for a whole second */ if (difftimeval(now, presleep) < 0.05) sleep(1); @@ -291,7 +293,8 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { (long)(now.tv_usec - presleep.tv_usec), difftimeval(now, presleep) ); - if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + + if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); break; } @@ -372,7 +375,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { char *buf; upsdrvquery_read_timeout(conn, tv); gettimeofday(&now, NULL); - if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { upsdebugx(5, "%s: requested timeout expired", __func__); break; } @@ -551,7 +554,7 @@ ssize_t upsdrvquery_request( continue; } - if (difftimeval(now, start) > tv.tv_sec + 0.000001 * tv.tv_usec) { + if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); return -1; From 1bcdc5c05d89c114174d2489f2581994fdc9f629 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:26:10 +0200 Subject: [PATCH 0788/1232] drivers/upsdrvquery.c: upsdrvquery_read_timeout(): fix retry-delays to 0.1sec (100msec, 100000usec) --- drivers/upsdrvquery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 085a4b0c68..05284086a4 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -243,9 +243,9 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { } upsdebugx(6, "%s: pipe read error, waiting for data", __func__); - /* Throttle down a bit */ + /* Throttle down a bit, 0.1 sec (10^5 * 10^-6) should do it conveniently */ gettimeofday(&presleep, NULL); - usleep(100); /* obsoleted in win32, so follow up below */ + usleep(100000); /* obsoleted in win32, so follow up below */ gettimeofday(&now, NULL); upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", @@ -264,7 +264,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { /* SetWaitableTimer() uses 100 nanosecond intervals, * and a negative value indicates relative time: */ - ft.QuadPart = -(10*100); /* 100 usec */ + ft.QuadPart = -(10*100000); /* 100 msec */ timer = CreateWaitableTimer(NULL, TRUE, NULL); SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); From 7abf62ef3d965e4c3e39ce4bca6f488c3088b804 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:30:46 +0200 Subject: [PATCH 0789/1232] drivers/upsdrvquery.c: upsdrvquery_read_timeout(): only log subsequent sleep-time diffs if we retried a sleep --- drivers/upsdrvquery.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 05284086a4..86f9a04c58 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -241,13 +241,16 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { upsdebugx(5, "%s: pipe read error (no incoming data), proceeding now", __func__); break; } - upsdebugx(6, "%s: pipe read error, waiting for data", __func__); + upsdebugx(6, "%s: pipe read error, still waiting for data", __func__); /* Throttle down a bit, 0.1 sec (10^5 * 10^-6) should do it conveniently */ gettimeofday(&presleep, NULL); usleep(100000); /* obsoleted in win32, so follow up below */ gettimeofday(&now, NULL); + /* NOTE: This code may report a "diff=1.-894714 (0.105286)" + * which looks bogus, but for troubleshooting we don't care + */ upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", __func__, presleep.tv_sec, presleep.tv_usec, now.tv_sec, now.tv_usec, @@ -270,29 +273,30 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); WaitForSingleObject(timer, INFINITE); CloseHandle(timer); - } - gettimeofday(&now, NULL); - upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", - __func__, presleep.tv_sec, presleep.tv_usec, - now.tv_sec, now.tv_usec, - difftime(now.tv_sec, presleep.tv_sec), - (long)(now.tv_usec - presleep.tv_usec), - difftimeval(now, presleep) - ); + gettimeofday(&now, NULL); + upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", + __func__, presleep.tv_sec, presleep.tv_usec, + now.tv_sec, now.tv_usec, + difftime(now.tv_sec, presleep.tv_sec), + (long)(now.tv_usec - presleep.tv_usec), + difftimeval(now, presleep) + ); + } /* If nothing was honored, doze off for a whole second */ - if (difftimeval(now, presleep) < 0.05) + if (difftimeval(now, presleep) < 0.05) { sleep(1); - gettimeofday(&now, NULL); - upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", - __func__, presleep.tv_sec, presleep.tv_usec, - now.tv_sec, now.tv_usec, - difftime(now.tv_sec, presleep.tv_sec), - (long)(now.tv_usec - presleep.tv_usec), - difftimeval(now, presleep) - ); + gettimeofday(&now, NULL); + upsdebugx(7, "%s: presleep=%ld.%06ld now=%ld.%06ld diff=%4.0f.%06ld (%f)", + __func__, presleep.tv_sec, presleep.tv_usec, + now.tv_sec, now.tv_usec, + difftime(now.tv_sec, presleep.tv_sec), + (long)(now.tv_usec - presleep.tv_usec), + difftimeval(now, presleep) + ); + } if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { upsdebugx(5, "%s: pipe read error, timeout exceeded", __func__); From dbed40f59bf79bdf5027ffd4beb5795af0ff2768 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:44:30 +0200 Subject: [PATCH 0790/1232] clients/upssched.c: start_daemon(): transplant STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO handling instead of hardcoded numbers, from common.c [#1879, #1881] --- clients/upssched.c | 58 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index aa1593240a..cbf84abac3 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -762,19 +762,51 @@ static void start_daemon(TYPE_FD lockfd) /* child */ - close(0); - close(1); - close(2); - - /* make fds 0-2 point somewhere defined */ - if (open("/dev/null", O_RDWR) != 0) - fatal_with_errno(EXIT_FAILURE, "open /dev/null"); - - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); - - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); + /* make fds 0-2 (typically) point somewhere defined */ +#ifdef HAVE_DUP2 + /* system can close (if needed) and (re-)open a specific FD number */ + if (1) { /* scoping */ + TYPE_FD devnull = open("/dev/null", O_RDWR); + if (devnull < 0) + fatal_with_errno(EXIT_FAILURE, "open /dev/null"); + + if (dup2(devnull, STDIN_FILENO) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); + if (dup2(devnull, STDOUT_FILENO) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); + if (dup2(devnull, STDERR_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + + close(devnull); + } +#else +# ifdef HAVE_DUP + /* opportunistically duplicate to the "lowest-available" FD number */ + close(STDIN_FILENO); + if (open("/dev/null", O_RDWR) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); + + close(STDOUT_FILENO); + if (dup(STDIN_FILENO) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDOUT"); + + close(STDERR_FILENO); + if (dup(STDIN_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDERR"); +# else + close(STDIN_FILENO); + if (open("/dev/null", O_RDWR) != STDIN_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); + + close(STDOUT_FILENO); + if (open("/dev/null", O_RDWR) != STDOUT_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); + + close(STDERR_FILENO); + if (open("/dev/null", O_RDWR) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); +# endif +#endif pipefd = open_sock(); From 701df0984e2f6e6ec7acaad615f7b405b8e1c5a2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 11:47:38 +0200 Subject: [PATCH 0791/1232] docs/man/index.txt: mention new sockdebug[8] man page --- docs/man/index.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/man/index.txt b/docs/man/index.txt index 65a5caf286..ad63c3dd4c 100644 --- a/docs/man/index.txt +++ b/docs/man/index.txt @@ -65,6 +65,7 @@ Developer manual pages - linkman:libupsclient-config[1] - linkman:nut-recorder[8] - linkman:skel[8] +- linkman:sockdebug[8] [[devclient]] Client library From 0ba826b43a782eadfe4d63ff1b6d5464ca75a147 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 11 May 2023 20:37:24 +0200 Subject: [PATCH 0792/1232] docs/man/sockdebug.txt: fix formatting; clarify standard state path handling (POSIX builds) [#1936] --- docs/man/sockdebug.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/man/sockdebug.txt b/docs/man/sockdebug.txt index 8ccdd3a042..e9b6d80839 100644 --- a/docs/man/sockdebug.txt +++ b/docs/man/sockdebug.txt @@ -13,9 +13,11 @@ SYNOPSIS *sockdebug* socketname For example (WIN32 and POSIX builds): + sockdebug.exe dummy-ups-UPS1 For example (POSIX-compliant systems using an alternate state path): + sockdebug /var/state/ups/dummy-ups-UPS1 DESCRIPTION @@ -52,6 +54,13 @@ configuration (which in turn may originate in the `ups.conf` file or be dynamically constructed for tests by calling the driver program with a `-s TMP` CLI option). +On POSIX systems, if this argument only represents a base name and not a +full path to the Unix socket file, the tool should first look for the file +in the current directory, and then fall back to configured (built-in) state +path or the value of `NUT_STATEPATH` environment variable, if set; e.g.: + + NUT_STATEPATH=/tmp ./server/sockdebug dummy-ups-UPS1 + AUTHORS ------- From 650fd598195298395ad79077acccd53c4144c176 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 12 May 2023 00:16:51 +0200 Subject: [PATCH 0793/1232] Update sockdebug.txt Fix markup (and a progname mention), add original code authors. --- docs/man/sockdebug.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/man/sockdebug.txt b/docs/man/sockdebug.txt index e9b6d80839..c29ba100e5 100644 --- a/docs/man/sockdebug.txt +++ b/docs/man/sockdebug.txt @@ -44,7 +44,7 @@ For more details see the `docs/sock-protocol.txt` file in NUT sources. OPTIONS ------- -*libupsclient-config* accepts the following options: +*sockdebug* accepts (and requires) the following option: *socketname*:: Either a full path (in POSIX builds) or the base name of device socket/pipe @@ -53,19 +53,25 @@ Either a full path (in POSIX builds) or the base name of device socket/pipe configuration (which in turn may originate in the `ups.conf` file or be dynamically constructed for tests by calling the driver program with a `-s TMP` CLI option). - ++ On POSIX systems, if this argument only represents a base name and not a full path to the Unix socket file, the tool should first look for the file in the current directory, and then fall back to configured (built-in) state path or the value of `NUT_STATEPATH` environment variable, if set; e.g.: - ++ +------ NUT_STATEPATH=/tmp ./server/sockdebug dummy-ups-UPS1 +------ AUTHORS ------- This manual page was written by Jim Klimov . +The program was originally written by +Russell Kroll (POSIX version), and by +Frederic Bohe (Windows version). + SEE ALSO -------- From e3bdc28476700c7396bdde912e5789ccb7ecb1d7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 13 May 2023 16:44:27 +0200 Subject: [PATCH 0794/1232] docs/man/Makefile.am: typo fix to not override man8_MANS definition --- docs/man/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 0441fdf015..e5f79bbaf7 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -322,7 +322,7 @@ endif if WITH_DEV man3_MANS = $(MAN3_DEV_PAGES) -man8_MANS = $(MAN8_DEV_PAGES) +man8_MANS += $(MAN8_DEV_PAGES) if !WITH_PKG_CONFIG man1_MANS = $(MAN1_DEV_PAGES) From 2b6791f1a9c6c154094c375841bac55872fdbe89 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 19 May 2023 12:45:50 +0200 Subject: [PATCH 0795/1232] docs/developers.txt: update notes for IDE (specifically NetBeans on Windows) setup --- docs/developers.txt | 198 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 13 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index 763e3498a3..b1f1c033be 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -434,8 +434,8 @@ Integrated Development Environments (IDEs) and debugging NUT ------------------------------------------------------------ Much of NUT has been coded using classic editors of developers' preference, -like `vi`, `nano`, Midnight Commander `mcedit`, NotePad++ and tools like -`meld` or WinMerge for file comparison and merge. +like `vi`, `nano`, Midnight Commander `mcedit`, `gedit`/`pluma`, NotePad++ +and tools like `meld` or WinMerge for file comparison and merge. Modern IDEs however do offer benefits, specifically for live debugging sessions in a more convenient fashion than with command-line `gdb` directly. @@ -443,7 +443,9 @@ They also simplify writing AsciiDoc files with real-time rendering support. NOTE: Due to use of `libtool` wrappers in "autotools" driven projects, it may be tricky to attach the debugger (mixing the correct `LD_LIBRARY_PATH` -or equivalent with a binary under a `.libs` subdirectory). +or equivalent with a binary under a `.libs` subdirectory; on some platforms +you may be better off copying shared objects to the directory with the binary +being tested). IDEs that were tested to work with NUT development and real-time debugger tracing include: @@ -456,25 +458,195 @@ tracing include: IDE notes on Windows ~~~~~~~~~~~~~~~~~~~~ +General settings for builds on Windows +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + When working in a native Windows environment with link:https://www.msys2.org/[MSYS2] (providing MinGW x64 among other things), -make sure it is in the `PATH`: Control Panel => "Edit the system environment -variables" => "Environment variables..." (button) => Edit or create New "Path" -setting => Make sure `C:\msys64\mingw64\bin` is there (assuming you installed -MSYS2 into `C:\msys64` by default). Restart the IDE (if already running) for -it to acknowledge the system configuration change. - -Otherwise, NetBeans for example claims there is no shell for it to run `make`, -and fails to start the built programs due to lack of DLL files it linked -against (such as `libssl` for networked part of the codebase). +you may need to ensure certain environment variables are set before you start +the IDE (shortcuts and wrappers that start your console apply them via shell). + +Also note that if you set them system-wide for your user profile (or wrap the +IDE start-up by a script to set them), it may compromise your ability to use +other MSYS2 profiles and/or other builds of these toolkits (packaged by e.g. +Git for Windows or PERL for Windows) generally, or in the same IDE session, +respectively. You may want to do this in a dedicated user account. + +Examples below assume you installed MSYS2 into `C:\msys64` (by default) and +are using the "MinGW X64" profile for GCC builds (nuances may differ for +32-bit, CLANG, UCRT and other profile variants): + +* Make sure its tools are in the `PATH`: ++ +Control Panel => "Edit the system environment variables" => + "Environment variables..." (button) => + "Edit..." or create "New..." `Path` setting ("User variable" level suffices) => + +** Make sure `C:\msys64\mingw64\bin` and `C:\msys64\usr\bin` are both there. +** Depending on further installed toolkits, you may want to add + `C:\Program Files\Git\cmd` or `C:\Program Files\Microsoft VS Code\bin` + (preferably use deployment-dependent spellings without white-space like + `Progra~1` to err on the safe side of variable expansions later). + +* Make sure that MSYS2 (and tools which integrate with it) know its home: ++ +Open Environment variables window as above, and + "Edit..." or create "New..." `MSYS_HOME` setting => + Set to `C:\msys64\mingw64\bin` +* Restart the IDE (if already running) for it to acknowledge the system + configuration change. + +Otherwise, NetBeans for example claims there is no shell for it to run `make` +or open Terminal pane windows, and fails to start the built programs due to +lack of DLL files it linked against (such as `libssl` usually needed for any +networked part of the codebase). You might still have to fiddle with DLL files built in other directories of the NUT project, when preparing to debug certain programs, e.g. for `dummy-ups` -you may need to: +testing you may need to: ```` :; cp ./clients/.libs/libupsclient-6.dll ./drivers/.libs/ ```` +GDB on Windows +^^^^^^^^^^^^^^ + +Examples below assume that whichever IDE you are using, the primary goal is +to debug some issues with NUT on that platform. + +This may require you to craft a configuration file for the GNU Debugger, +e.g. `C:\Users\abuild\.gdbinit` for the examples below. One is not required +however, and may be missing. + +Another thing to keep in mind is that with `libtool` involved, the actual +binary for testing would be in a `.libs` subdirectory and you may have some +fun with ensuring that DLLs are found to start them -- see the notes above. + +NetBeans on Windows +^^^^^^^^^^^^^^^^^^^ + +If installing newer link:https://netbeans.apache.org/[Apache NetBeans] +releases you may need to enable the use of "NetBeans 8.2 Plugin Portal" +(check under Tools/Plugins/Settings) and install the "C/C++" plugin only +available there at the moment. In turn, that older build of a plugin package +may require that your system provides the `unpack200` tool which was shipped +with JDK11 or older (you may have to install that just to get the tool, or +copy its binary from another system). + +Under Tools/Options menu open the C/C++ tab and further its Build Tools sub-tab. + +NOTE: NetBeans allows you to easily define different Tool Collections, +including those associated with a different build host (accessible over SSH +and source/build paths optionally shared over NFS or similar technology, or +copied over). This allows you to run the IDE on your desktop while debugging +a build running on a server or embedded system. + +Make sure you have a MinGW Tool Collection for the "localhost" build host with +such settings as: + +| Family | GNU MinGW | +| Encoding | UTF-8 | +| Base Directory | `C:\msys64\mingw64\bin` | +| C Compiler | `C:\msys64\mingw64\bin\gcc.exe` | +| C++ Compiler | `C:\msys64\mingw64\bin\g++.exe` | +| Assembler | `C:\msys64\mingw64\bin\as.exe` | +| Make Command | `C:\msys64\usr\bin\make.exe` | +| Debugger Command | `C:\msys64\mingw64\bin\gdb.exe` | + +In the Code Assistance sub-tab check that there are toolkit-specific and +general include paths, e.g. both C and C++ Compiler settings might involve: + +| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include` | +| `C:\msys64\mingw64\include` | +| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include-fixed` | +| `C:\msys64\mingw64\x86_64-w64-mingw32\include` | + +On top of that, C++ Compiler settings may include: + +| `C:\msys64\mingw64\include\12.2.0` | +| `C:\msys64\mingw64\include\12.2.0\x86_64-w64-mingw32` | +| `C:\msys64\mingw64\include\12.2.0\backward` | + +In the "Other" sub-tab, set default standards to C99 and C++11 to match common +NUT codebase expectations. + +Finally, open/create a "nut" project pointing to your git checkout workspace. + +Next part of configuration regards build/debug configurations, which you can +find on the toolbar or as File / Project Properties. + +The main configuration for debugging a particular binary (and NUT has tons +of those, good luck in case you want to debug several simultaneously) is +in the *Run* and *Debug* categories. You may want to define different +Configuration profiles to track the individual Run/Debug settings for +different tested binaries, while the Build/Make settings would remain the same. +Alternatively, you may set the *Make* category's "Build Result" as the path to +the binary you would test, and use `${OUTPUT_PATH}` variable as its name in +the "Run Command" (still likely need custom arguments) and "Symbol File" below. + +When you investigate interactions of two or more programs, but only want to +debug (step through) just one of them, you are advised to run each of the +others from a dedicated terminal session, and just bump their debug verbosity. + +* In the *Build* category, set the Build Host (localhost) and Tool Collection + (MinGW). In expert part of the settings, un-check "platform-independent" + and revise that the `TOOLS_PATH=C:\msys64\mingw64\bin` while the + `UTILITIES_PATH=C:\msys64\usr\bin`. + +* In the *Pre-Build* category likely keep the Working Directory as `.` and + the `Pre-Build First` generally unchecked (so only enable it to reconfigure + the project, which takes time and is not needed for every rebuild iteration), + but you may still pre-set the Command line to something like the following + (on one line): ++ +------ +bash -c "rm -f configure Makefile; ./autogen.sh && + ./configure CC='${IDE_CC}' CXX='${IDE_CXX}' + --with-all=auto --with-docs=skip" +------ ++ +And possibly throw in `CFLAGS` and `CXXFLAGS` set to `-g3 -gdwarf-2` or similar. ++ +In some cases, NOT specifying the `CC`, `CXX` and the flags actually succeeds +while passing their options fails the configuration ("Compiler can not create +executables" etc.) probably due to path resolution issues between the native +and MinGW environments. ++ +In practice, you may have an easier time using NUT `./ci_build.sh` helper or +running a more specific `./autogen.sh && ./configure ...` spell similar to +the above example or customized otherwise, in the MinGW x64 console window +to actually configure a NUT source code setup, than to maintain one via the IDE. +Running (re-)builds with the IDE (as you just edit non-recipe sources and +iterate with a debugger) using externally configured Makefiles works fine. + +* In the *Make* category you may want to customize for parallelized builds on + multi-CPU systems with something like: +** Build Command: `${MAKE} -j 6 -f Makefile` +** Clean Command: `${MAKE} -f Makefile clean` + +* In the *Run* category you should set the "Run Command" to point to your + binary (note the `.libs` sub-directory, and see comments above regarding + possibly needed copies of shared objects) and its arguments (all on one + line), e.g.: ++ +------ +C:\Users\abuild\Desktop\nut\drivers\.libs\usbhid-ups.exe -s ups -x port=auto + -d1 -DDDDDD +------ ++ +Other useful settings may be to keep "Build First" checked, and if the +"Internal Terminal" does not work for you as the debugged program's console -- +set the "Console Type" to "External Terminal" of type "Command Window". +Unfortunately, NetBeans on Windows may have issues running terminal tabs +unless CygWin is installed. + +* In the *Debug* category you should set the "Symbol File" to point to your + tested binary (e.g. `C:\Users\abuild\Desktop\nut\drivers\.libs\usbhid-ups.exe` + to match the "Run Command" example above) and specify "Follow Fork Mode" as + "child" and "Detach On Fork" as "off". "Reverse Debugging" may be useful too + in some situations. Finally, select your "Gdb Init File" if you have one, + e.g. `C:\Users\abuild\.gdbinit`. + //////// TODO: Expand on adding include and library paths to NetBeans on Windows. Plugins: unpack200 from JDK11 or older to install NB8.2 repo C/C++ plugins. From 5c6eaf8f911acd0a09cee9fd1cbb6a5358c12795 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 19 May 2023 12:45:50 +0200 Subject: [PATCH 0796/1232] docs/developers.txt: update notes for IDE (specifically NetBeans on Windows) setup --- docs/nut.dict | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 703c81e6a3..de54a9a9cc 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3133 utf-8 +personal_ws-1.1 en 3141 utf-8 AAS ABI ACFAIL @@ -233,6 +233,7 @@ Cuvellard Cyber CyberPower CyberShield +CygWin Cygwin DATACABLE DATAPATH @@ -256,6 +257,7 @@ DF DHEA DIGYS DISCHRG +DLLs DMF DN DNS @@ -958,6 +960,7 @@ PresentStatus Priv Procomm ProductID +Progra Proxmox Prynych Pulizzi @@ -1937,8 +1940,11 @@ gcpp gd gd's gdb +gdbinit gdlib +gdwarf ge +gedit genericsups genericups genesisII @@ -2473,6 +2479,7 @@ outliers pF pacman pacstrap +parallelized param paramkeywords parsable @@ -2516,6 +2523,7 @@ pkgin plaintext plugin plugnplay +pluma pmset pmu png From b506159d2b715273c9d65c07ec95ff486e748f0a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 19 May 2023 14:54:18 +0200 Subject: [PATCH 0797/1232] docs/developers.txt: update notes for IDE setup for debug symbols --- docs/developers.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index b1f1c033be..65284cd0fc 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -508,6 +508,17 @@ testing you may need to: :; cp ./clients/.libs/libupsclient-6.dll ./drivers/.libs/ ```` +To ensure builds with debug symbols, you may add `CFLAGS` and `CXXFLAGS` set +to `-g3 -gdwarf-2` or similar to `configure` options, or if that confuses +the cross-build (it tends to assume those values are part of GCC path), +you may have to hack them into your local copy of `configure.ac`, after the +`AM_INIT_AUTOMAKE([subdir-objects])` line: +```` +CFLAGS="$CFLAGS -g3 -gdwarf-2" +CXXFLAGS="$CXXFLAGS -g3 -gdwarf-2" +```` +...and re-run the `./autogen.sh` script. + GDB on Windows ^^^^^^^^^^^^^^ @@ -605,8 +616,6 @@ bash -c "rm -f configure Makefile; ./autogen.sh && --with-all=auto --with-docs=skip" ------ + -And possibly throw in `CFLAGS` and `CXXFLAGS` set to `-g3 -gdwarf-2` or similar. -+ In some cases, NOT specifying the `CC`, `CXX` and the flags actually succeeds while passing their options fails the configuration ("Compiler can not create executables" etc.) probably due to path resolution issues between the native From c6b7aef0cd3cd55dbb31d4d590717421b5f3d8aa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 19 May 2023 15:16:27 +0200 Subject: [PATCH 0798/1232] docs/developers.txt: chapter on VSCode setup --- docs/developers.txt | 126 +++++++++++++++++++++++++++++++++++++++++--- docs/nut.dict | 34 +++++++++++- 2 files changed, 153 insertions(+), 7 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index 65284cd0fc..dc8e5be2ad 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -656,15 +656,129 @@ unless CygWin is installed. in some situations. Finally, select your "Gdb Init File" if you have one, e.g. `C:\Users\abuild\.gdbinit`. -//////// -TODO: Expand on adding include and library paths to NetBeans on Windows. -Plugins: unpack200 from JDK11 or older to install NB8.2 repo C/C++ plugins. +Microsoft VS Code +^^^^^^^^^^^^^^^^^ + +With this IDE you can benefit from numerous Extensions from its Marketplace, +the ones found useful for NUT development and debugging include: + +* AsciiDoc (by asciidoctor) +* EditorConfig for VS Code (by EditorConfig) +* C/C++ (by Microsoft) +* C/C++ Extension pack (by Microsoft) +* Makefile tool (by Microsoft) +* MSYS2/Cygwin/MinGW/Clang support (by okhlybov) +* Native Debug (GDB, LLDB ... Debugger support; by WebFreak) + +Configurations are tracked locally in JSON files where you would need to add +some entries. Examples below highlight the needed keys and values; your files +may have others: + +* `.vscode/launch.json` (can create one via Run/Add Configuration... menu + defines ways to launch the debug session for a program: ++ +------ +{ + "configurations": [ + { + "name": "CPPDBG GDB usbhid-ups", + "type": "cppdbg", + "request": "launch", + "program": "C:\\Users\\abuild\\Desktop\\nut\\drivers\\.libs\\usbhid-ups.exe", + "additionalSOLibSearchPath": "C:\\Users\\abuild\\Desktop\\nut\\.inst\\mingw64\\bin", + "stopAtConnect": true, + "args": ["-s", "ups", "-DDDDDD", "-d1", "-x", "port=auto"], + "stopAtEntry": false, + "cwd": "C:\\Users\\abuild\\Desktop\\nut", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "C:\\msys64\\mingw64\\bin\\gdb.exe", + "targetArchitecture": "x64", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ], + "preLaunchTask": "make usbhid-ups" + }, + { + // Alternately with LLDB (clang), the rest looks like above: + "name": "CPPDBG LLDB usbhid-ups", + "MIMode": "lldb", + "miDebuggerPath": "C:\\msys64\\usr\\bin\\lldb.exe", + }, + ... + ] +} +------ + +* `.vscode/tasks.json` defines other tasks, such as the `preLaunchTask` + mentioned above (assuming you have configured the build externally in + the MinGW x64 terminal session): ++ +------ +{ + "tasks": [ + { + "type": "shell", + "label": "make usbhid-ups", + "command": "C:\\msys64\\usr\\bin\\make usbhid-ups", + "options": { + "cwd": "${workspaceFolder}/drivers" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + ... + ] +} +------ -TODO: Expand on tools.json and launcher.json in VSCode on Windows +* `.vscode/c_cpp_properties.json` defines general compiler settings, e.g.: ++ +------ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "C:\\msys64\\mingw64\\include\\libusb-1.0", + "C:\\msys64\\mingw64\\include", + "C:\\msys64\\usr\\include" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "compilerPath": "C:\\msys64\\mingw64\\bin\\gcc.exe", + "cStandard": "c99", + "cppStandard": "c++11", + "intelliSenseMode": "windows-gcc-x64", + "configurationProvider": "ms-vscode.makefile-tools" + } + ], + "version": 4 +} +------ -TODO: Expand on envvars settings for MSYS to be callable on Windows -(e.g. avoid NetBeans claims of missing shell). +//////// +TODO: Make note of settings (and Run as Administrator) to use symlinks in MinGW x64. Check if required for sane (iterative re-)builds? ;) //////// diff --git a/docs/nut.dict b/docs/nut.dict index de54a9a9cc..b2c54b38eb 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3141 utf-8 +personal_ws-1.1 en 3173 utf-8 AAS ABI ACFAIL @@ -188,6 +188,7 @@ CPAN CPE CPM CPP +CPPDBG CPPFLAGS CPUs CRC @@ -321,6 +322,7 @@ ETIME EUROCASE EXtreme Economou +EditorConfig Edlman Edmundsson Edscott @@ -594,6 +596,7 @@ LINEV LISTINSTCMD LISTRW LISTVARS +LLDB LLNC LOADPCT LOCKFN @@ -644,6 +647,7 @@ MEC MEGATAEC MH MIBs +MIMode MINLINEV MINSUPPLIES MINTIMEL @@ -1369,6 +1373,7 @@ WTU Waldie WantedBy WatchdogSec +WebFreak Werror Wextra WhizBang @@ -1436,6 +1441,7 @@ adb addcmd addenum addinfo +additionalSOLibSearchPath addr addrange addvars @@ -1496,6 +1502,7 @@ armhf asapm ascii asciidoc +asciidoctor asem aspell ast @@ -1613,6 +1620,7 @@ busybox bv bypassvolts byv +cStandard cablepower calloc cb @@ -1692,9 +1700,11 @@ colspan command's commandlen compat +compilerPath conf config configs +configurationProvider configureaz configureaza confpath @@ -1712,7 +1722,9 @@ cout coverity cp cpp +cppStandard cppcheck +cppdbg cppnit cppunit cpqpower @@ -1737,6 +1749,7 @@ cua cuaa customizations cvt +cwd cx cyberpower d'un @@ -1887,6 +1900,7 @@ executables executeCommand execve extendedhistory +externalConsole extradata fabula facto @@ -2044,6 +2058,7 @@ ie ietf ifdef ifndef +ignoreFailures ignorelb ignoreoff ignoresab @@ -2052,6 +2067,7 @@ illumos im img imv +includePath includedir inductor infos @@ -2072,6 +2088,8 @@ installcheck installurl instcmd instcmds +intel +intelliSenseMode intercharacter internet interoperability @@ -2101,6 +2119,7 @@ ipmimonitoring ipmipsu ippon ipv +isDefault isbmex ish iso @@ -2209,6 +2228,7 @@ listDeviceClients listdef littleguy lk +lldb lm ln loadPercentage @@ -2254,6 +2274,7 @@ mailx maintainer's maintainership maj +makefile makevartable mandir manpage @@ -2287,6 +2308,7 @@ mge mgeups mgexml mgmt +miDebuggerPath mib mibs microcontroller @@ -2441,6 +2463,7 @@ offtimedays oftd oids ok +okhlybov oksh ol oldmac @@ -2559,6 +2582,7 @@ ppro pragma pragmas pre +preLaunchTask prepend prepended preprocess @@ -2571,6 +2595,7 @@ prgshut printf privPassword privProtocol +problemMatcher probu proc productid @@ -2716,6 +2741,7 @@ setpci setpoint setq setuid +setupCommands setvar setvar's sfr @@ -2793,6 +2819,8 @@ stderr stdlib stdout stdupsv +stopAtConnect +stopAtEntry stopIP str strace @@ -2815,6 +2843,7 @@ stylesheet stylesheets su subcommand +subdir subdirectories subdirectory subdriver @@ -2863,6 +2892,7 @@ tabledef tagname tapswitchdelay tapswitchphase +targetArchitecture tbody tcflush tcgetattr @@ -3068,6 +3098,7 @@ vo vod voltronic von +vscode wDescriptorLength waitbeforereconnect wakeup @@ -3088,6 +3119,7 @@ wmnut wordformat workflow workspace +workspaceFolder workspaces writability writeinfo From 687cc17d2a60eb8d10af86c27bfc87cb62d0488f Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Fri, 19 May 2023 20:49:21 +0200 Subject: [PATCH 0799/1232] tools/gitlog2changelog.py: fix expected git log format Update gitlog2changelog.py script to ensure git log format is not influenced by user git configuration. --- tools/gitlog2changelog.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index dfdf2fb403..aa77f74b1a 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -22,7 +22,7 @@ fin_mode = 0 fin_chop = 0 try: p = subprocess.Popen( - ['git', 'log', '--summary', '--stat', '--no-merges', '--date=short', ('%s' % rev_range)], + ['git', 'log', '--pretty=medium', '--summary', '--stat', '--no-merges', '--date=short', ('%s' % rev_range)], encoding='utf-8', close_fds = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) fin, ferr = p.communicate() @@ -32,7 +32,7 @@ try: fin = fin.splitlines() fin_mode = 3 except TypeError: - fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') + fin = os.popen('git log --pretty=medium --summary --stat --no-merges --date=short %s' % rev_range, 'r') fin_mode = 2 fin_chop = 1 From 56cb023632e2348d36c2eeae65d53a2d32b8834d Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Fri, 19 May 2023 20:51:00 +0200 Subject: [PATCH 0800/1232] tools/gitlog2changelog.py: apply Black suggestions Apply on gitlog2changelog.py code change suggestions from Black Python code formatter. --- tools/gitlog2changelog.py.in | 68 ++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index aa77f74b1a..3d10cdbe53 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -8,11 +8,11 @@ from textwrap import TextWrapper import sys import subprocess -rev_range = 'HEAD' +rev_range = "HEAD" if len(sys.argv) > 1: base = sys.argv[1] - rev_range = '%s..HEAD' % base + rev_range = "%s..HEAD" % base # Execute git log with the desired command line options. # Support Python2 and Python3 (esp. 3.6 and earlier) semantics @@ -22,25 +22,41 @@ fin_mode = 0 fin_chop = 0 try: p = subprocess.Popen( - ['git', 'log', '--pretty=medium', '--summary', '--stat', '--no-merges', '--date=short', ('%s' % rev_range)], - encoding='utf-8', close_fds = True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + [ + "git", + "log", + "--pretty=medium", + "--summary", + "--stat", + "--no-merges", + "--date=short", + ("%s" % rev_range), + ], + encoding="utf-8", + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) fin, ferr = p.communicate() if p.wait() != 0: - print ("ERROR getting git changelog") + print("ERROR getting git changelog") system.exit(1) fin = fin.splitlines() fin_mode = 3 except TypeError: - fin = os.popen('git log --pretty=medium --summary --stat --no-merges --date=short %s' % rev_range, 'r') + fin = os.popen( + "git log --pretty=medium --summary --stat --no-merges --date=short %s" + % rev_range, + "r", + ) fin_mode = 2 fin_chop = 1 # Create a ChangeLog file in the current directory. if fin_mode == 3: - fout = open('ChangeLog', 'w', encoding='UTF-8') + fout = open("ChangeLog", "w", encoding="UTF-8") else: - fout = open('ChangeLog', 'w') + fout = open("ChangeLog", "w") # Set up the loop variables in order to locate the blocks we want authorFound = False @@ -57,7 +73,7 @@ wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t ") # The main part of the loop for line in fin: # The commit line marks the start of a new commit object. - if line.startswith('commit'): + if line.startswith("commit"): # Start all over again... authorFound = False dateFound = False @@ -69,32 +85,32 @@ for line in fin: continue # Match the author line and extract the part we want # (Don't use startswith to allow Author override inside commit message.) - elif 'Author:' in line: - authorList = re.split(': ', line, 1) + elif "Author:" in line: + authorList = re.split(": ", line, 1) try: author = authorList[1] - author = author[0:len(author) - fin_chop] + author = author[0 : len(author) - fin_chop] authorFound = True except: - print ("Could not parse authorList = '%s'" % (line)) + print("Could not parse authorList = '%s'" % (line)) # Match the date line - elif line.startswith('Date:'): - dateList = re.split(': ', line, 1) + elif line.startswith("Date:"): + dateList = re.split(": ", line, 1) try: date = dateList[1] - date = date[0:len(date) - fin_chop] + date = date[0 : len(date) - fin_chop] dateFound = True except: - print ("Could not parse dateList = '%s'" % (line)) + print("Could not parse dateList = '%s'" % (line)) # The Fossil-IDs are ignored: - elif line.startswith(' Fossil-ID:') or line.startswith(' [[SVN:'): + elif line.startswith(" Fossil-ID:") or line.startswith(" [[SVN:"): continue # The svn-id lines are ignored - elif ' git-svn-id:' in line: + elif " git-svn-id:" in line: continue # The sign off line is ignored too - elif 'Signed-off-by' in line: + elif "Signed-off-by" in line: continue # Extract the actual commit message for this commit elif authorFound & dateFound & messageFound == False: @@ -112,12 +128,12 @@ for line in fin: else: message = message + " " + line.strip() # If this line is hit all of the files have been stored for this commit - elif re.search('files? changed', line): + elif re.search("files? changed", line): filesFound = True continue # Collect the files for this commit. FIXME: Still need to add +/- to files elif authorFound & dateFound & messageFound: - fileList = re.split(' \| ', line, 2) + fileList = re.split(" \| ", line, 2) if len(fileList) > 1: if len(files) > 0: files = files + ", " + fileList[0].strip() @@ -145,8 +161,8 @@ for line in fin: namesF = None namesM = None try: - namesM = sorted(re.split(r'[ ,]', message.split(":")[0])) - namesF = sorted(re.split(r'[ ,]', files)) + namesM = sorted(re.split(r"[ ,]", message.split(":")[0])) + namesF = sorted(re.split(r"[ ,]", files)) except: pass @@ -158,7 +174,7 @@ for line in fin: # Write out the commit line fout.write(wrapper.fill(commitLine) + "\n") - #Now reset all the variables ready for a new commit block. + # Now reset all the variables ready for a new commit block. authorFound = False dateFound = False messageFound = False From d0e8892a54dc2570a78e1f629c93ac16394bc05e Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Fri, 19 May 2023 20:54:33 +0200 Subject: [PATCH 0801/1232] tools/gitlog2changelog.py: apply Flake8 suggestions Apply on gitlog2changelog.py most code change suggestions from Flake8 Python style guide enforcement tool. --- tools/gitlog2changelog.py.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 3d10cdbe53..5eeb06c497 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -3,7 +3,8 @@ # Minor changes for NUT by Charles Lepple # Distributed under the terms of the GNU General Public License v2 or later -import string, re, os +import re +import os from textwrap import TextWrapper import sys import subprocess @@ -40,7 +41,7 @@ try: fin, ferr = p.communicate() if p.wait() != 0: print("ERROR getting git changelog") - system.exit(1) + sys.exit(1) fin = fin.splitlines() fin_mode = 3 except TypeError: @@ -113,7 +114,7 @@ for line in fin: elif "Signed-off-by" in line: continue # Extract the actual commit message for this commit - elif authorFound & dateFound & messageFound == False: + elif authorFound & dateFound & messageFound is False: # Find the commit message if we can if len(line) == fin_chop: if messageNL: @@ -133,7 +134,7 @@ for line in fin: continue # Collect the files for this commit. FIXME: Still need to add +/- to files elif authorFound & dateFound & messageFound: - fileList = re.split(" \| ", line, 2) + fileList = re.split(r' \| ', line, 2) if len(fileList) > 1: if len(files) > 0: files = files + ", " + fileList[0].strip() From 33c6de89dcd6d38fb27b09c333838d2da749fdce Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 23 May 2023 14:46:01 +0200 Subject: [PATCH 0802/1232] Jenkinsfile-dynamatrix: withEnvOptional() was refactored from "infra" to a standalone step --- Jenkinsfile-dynamatrix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index 967c12081e..3102f96e8c 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -261,7 +261,7 @@ set | sort -n """ } } - infra.withEnvOptional(dynacfgPipeline.defaultTools) { + withEnvOptional(dynacfgPipeline.defaultTools) { unstashCleanSrc(dynacfgPipeline.stashnameSrc) buildMatrixCellCI(dynacfgPipeline, dsbcClone, stageNameClone) //buildMatrixCellCI(dynacfgPipeline, dsbc, stageName) @@ -289,7 +289,7 @@ set | sort -n """ } } - infra.withEnvOptional(dynacfgPipeline.defaultTools) { + withEnvOptional(dynacfgPipeline.defaultTools) { unstashCleanSrc(dynacfgPipeline.stashnameSrc) def dynacfgPipeline_ciBuild = dynacfgPipeline.clone() dynacfgPipeline_ciBuild.buildSystem = 'ci_build.sh' From 6d618cb9132e71d94a30af93b0decf7a4c058a27 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 23 May 2023 15:15:54 +0200 Subject: [PATCH 0803/1232] docs/developers.txt: fix asciidoc table markup; update a few comments for Windows development environments --- docs/developers.txt | 74 +++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index dc8e5be2ad..51542fac93 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -466,15 +466,23 @@ link:https://www.msys2.org/[MSYS2] (providing MinGW x64 among other things), you may need to ensure certain environment variables are set before you start the IDE (shortcuts and wrappers that start your console apply them via shell). -Also note that if you set them system-wide for your user profile (or wrap the -IDE start-up by a script to set them), it may compromise your ability to use -other MSYS2 profiles and/or other builds of these toolkits (packaged by e.g. -Git for Windows or PERL for Windows) generally, or in the same IDE session, -respectively. You may want to do this in a dedicated user account. +WARNING: If you set such environment variables system-wide for your user +profile (or wrap the IDE start-up by a script to set them), it may compromise +your ability to use *other* MSYS2 profiles and/or other builds of these +toolkits (packaged by e.g. Git for Windows or PERL for Windows projects) +generally, or in the same IDE session, respectively. +You may want to do this in a dedicated user account! Examples below assume you installed MSYS2 into `C:\msys64` (by default) and are using the "MinGW X64" profile for GCC builds (nuances may differ for -32-bit, CLANG, UCRT and other profile variants): +32-bit, CLANG, UCRT and other profile variants). + +Also keep in mind that not all dependencies and tools involved in a +fully-fledged NUT build are easily available or usable on Windows (e.g. +the spell checker). See the link:config-prereqs.txt[] for better detailed +package lists for different operating systems including Windows, and feel +welcome to post pull requests with suggestions about new tool-chains that +might fare better than those already tried and documented. * Make sure its tools are in the `PATH`: + @@ -504,19 +512,19 @@ networked part of the codebase). You might still have to fiddle with DLL files built in other directories of the NUT project, when preparing to debug certain programs, e.g. for `dummy-ups` testing you may need to: -```` +------ :; cp ./clients/.libs/libupsclient-6.dll ./drivers/.libs/ -```` +------ To ensure builds with debug symbols, you may add `CFLAGS` and `CXXFLAGS` set to `-g3 -gdwarf-2` or similar to `configure` options, or if that confuses the cross-build (it tends to assume those values are part of GCC path), you may have to hack them into your local copy of `configure.ac`, after the `AM_INIT_AUTOMAKE([subdir-objects])` line: -```` +------ CFLAGS="$CFLAGS -g3 -gdwarf-2" CXXFLAGS="$CXXFLAGS -g3 -gdwarf-2" -```` +------ ...and re-run the `./autogen.sh` script. GDB on Windows @@ -540,9 +548,9 @@ If installing newer link:https://netbeans.apache.org/[Apache NetBeans] releases you may need to enable the use of "NetBeans 8.2 Plugin Portal" (check under Tools/Plugins/Settings) and install the "C/C++" plugin only available there at the moment. In turn, that older build of a plugin package -may require that your system provides the `unpack200` tool which was shipped -with JDK11 or older (you may have to install that just to get the tool, or -copy its binary from another system). +may require that your system provides the `unpack200(.exe)` tool which +was shipped with JDK11 or older (you may have to install that just to +get the tool, or copy its binary from another system). Under Tools/Options menu open the C/C++ tab and further its Build Tools sub-tab. @@ -555,28 +563,36 @@ a build running on a server or embedded system. Make sure you have a MinGW Tool Collection for the "localhost" build host with such settings as: -| Family | GNU MinGW | -| Encoding | UTF-8 | -| Base Directory | `C:\msys64\mingw64\bin` | -| C Compiler | `C:\msys64\mingw64\bin\gcc.exe` | -| C++ Compiler | `C:\msys64\mingw64\bin\g++.exe` | -| Assembler | `C:\msys64\mingw64\bin\as.exe` | -| Make Command | `C:\msys64\usr\bin\make.exe` | -| Debugger Command | `C:\msys64\mingw64\bin\gdb.exe` | +|=== +| Option name | Sample value + +| Family | GNU MinGW +| Encoding | UTF-8 +| Base Directory | `C:\msys64\mingw64\bin` +| C Compiler | `C:\msys64\mingw64\bin\gcc.exe` +| C++ Compiler | `C:\msys64\mingw64\bin\g++.exe` +| Assembler | `C:\msys64\mingw64\bin\as.exe` +| Make Command | `C:\msys64\usr\bin\make.exe` +| Debugger Command | `C:\msys64\mingw64\bin\gdb.exe` +|=== In the Code Assistance sub-tab check that there are toolkit-specific and general include paths, e.g. both C and C++ Compiler settings might involve: -| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include` | -| `C:\msys64\mingw64\include` | -| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include-fixed` | -| `C:\msys64\mingw64\x86_64-w64-mingw32\include` | +|=== +| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include` +| `C:\msys64\mingw64\include` +| `C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\12.2.0\include-fixed` +| `C:\msys64\mingw64\x86_64-w64-mingw32\include` +|=== On top of that, C++ Compiler settings may include: -| `C:\msys64\mingw64\include\12.2.0` | -| `C:\msys64\mingw64\include\12.2.0\x86_64-w64-mingw32` | -| `C:\msys64\mingw64\include\12.2.0\backward` | +|=== +| `C:\msys64\mingw64\include\12.2.0` +| `C:\msys64\mingw64\include\12.2.0\x86_64-w64-mingw32` +| `C:\msys64\mingw64\include\12.2.0\backward` +|=== In the "Other" sub-tab, set default standards to C99 and C++11 to match common NUT codebase expectations. @@ -621,7 +637,7 @@ while passing their options fails the configuration ("Compiler can not create executables" etc.) probably due to path resolution issues between the native and MinGW environments. + -In practice, you may have an easier time using NUT `./ci_build.sh` helper or +NOTE: In practice, you may have an easier time using NUT `./ci_build.sh` helper or running a more specific `./autogen.sh && ./configure ...` spell similar to the above example or customized otherwise, in the MinGW x64 console window to actually configure a NUT source code setup, than to maintain one via the IDE. From ddab8f9572a393ea5830227bacc24175fbed388c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 23 May 2023 15:29:46 +0200 Subject: [PATCH 0804/1232] docs/developers.txt: add a mention of IntelliJ IDEA --- docs/developers.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/developers.txt b/docs/developers.txt index 51542fac93..49a0a7c410 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -455,6 +455,10 @@ tracing include: * Apache NetBeans 17 on Windows with MSYS2 support (as MinGW toolkit); * Visual Studio Code (VSCode) on Windows with MSYS2 support. +Some supporting maintenance and development is doable with IntelliJ IDEA, +making some things easier to do than with a simple Notepad, but it does +not handle C/C++ development as such. + IDE notes on Windows ~~~~~~~~~~~~~~~~~~~~ @@ -793,6 +797,25 @@ may have others: ------ +IntelliJ IDEA +^^^^^^^^^^^^^ + +It is worth mentioning IntelliJ IDEA as another free (as of Community Edition) +and popular IDE, however it is of limited use for NUT development. + +Its ecosystem does feature a good AsciiDoc plugin, Python and of course the +Java/Groovy support, so is helpful for maintenance of NUT documentation, +helper scripts and CI recipes. + +It lacks however C/C++ language support (allegedly a different product in the +IntelliJ portfolio is dedicated to that), so for the core NUT project sources +it is just a fancy text editor (with `.editorconfig` support) without syntax +highlighting or codebase cross-reference aids, build/run/debug support, etc. + +Still, it is possible to run builds and tests in embedded or external terminal +session -- so it is not worse than editing with legacy tools, and navigation +or code-base-wide search is arguably easier. + //////// TODO: Make note of settings (and Run as Administrator) to use symlinks in MinGW x64. From 432698dab6c0cd2f421a3fe35337255f1d258d0e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 23 May 2023 15:32:57 +0200 Subject: [PATCH 0805/1232] docs/developers.txt: typo fix --- docs/developers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developers.txt b/docs/developers.txt index 49a0a7c410..76b2fd8d04 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -804,7 +804,7 @@ It is worth mentioning IntelliJ IDEA as another free (as of Community Edition) and popular IDE, however it is of limited use for NUT development. Its ecosystem does feature a good AsciiDoc plugin, Python and of course the -Java/Groovy support, so is helpful for maintenance of NUT documentation, +Java/Groovy support, so IDEA is helpful for maintenance of NUT documentation, helper scripts and CI recipes. It lacks however C/C++ language support (allegedly a different product in the From c8a4ef1045572a043041d67f01d98cddba20fa8b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 24 May 2023 17:06:51 +0200 Subject: [PATCH 0806/1232] docs/nut.dict: bump for IntelliJ --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index b2c54b38eb..aeb8f9aa10 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3173 utf-8 +personal_ws-1.1 en 3174 utf-8 AAS ABI ACFAIL @@ -517,6 +517,7 @@ Infosec Innova Integrators IntelCC +IntelliJ InvCDly InvCPol InvMin From 494a17a9f3af9d9e4303b2b701d67abfaee5ef6c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 26 May 2023 12:01:47 +0200 Subject: [PATCH 0807/1232] docs/developers.txt: reword a bit about IDE support --- docs/developers.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index 76b2fd8d04..b6e1984e59 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -510,8 +510,8 @@ Open Environment variables window as above, and Otherwise, NetBeans for example claims there is no shell for it to run `make` or open Terminal pane windows, and fails to start the built programs due to -lack of DLL files it linked against (such as `libssl` usually needed for any -networked part of the codebase). +lack of DLL files they were linked against (such as `libssl` usually needed +for any networked part of the codebase). You might still have to fiddle with DLL files built in other directories of the NUT project, when preparing to debug certain programs, e.g. for `dummy-ups` @@ -548,13 +548,14 @@ fun with ensuring that DLLs are found to start them -- see the notes above. NetBeans on Windows ^^^^^^^^^^^^^^^^^^^ -If installing newer link:https://netbeans.apache.org/[Apache NetBeans] -releases you may need to enable the use of "NetBeans 8.2 Plugin Portal" -(check under Tools/Plugins/Settings) and install the "C/C++" plugin only -available there at the moment. In turn, that older build of a plugin package -may require that your system provides the `unpack200(.exe)` tool which -was shipped with JDK11 or older (you may have to install that just to -get the tool, or copy its binary from another system). +When you install newer link:https://netbeans.apache.org/[Apache NetBeans] +releases (14, 17 as of this writing), you may need to enable the use of +"NetBeans 8.2 Plugin Portal" (check under Tools/Plugins/Settings) and +install the "C/C++" plugin only available there at the moment. +In turn, that older build of a plugin package may require that your system +provides the `unpack200(.exe)` tool which was shipped with JDK11 or older +(you may have to install that just to get the tool, or copy its binary from +another system). Under Tools/Options menu open the C/C++ tab and further its Build Tools sub-tab. From 2675c4b21b708619cfea397d68168ac3f28be317 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 26 May 2023 12:32:55 +0200 Subject: [PATCH 0808/1232] docs/documentation.txt: refer to HCL from near DDL --- docs/documentation.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/documentation.txt b/docs/documentation.txt index 2a855b9f01..7abd099f7e 100644 --- a/docs/documentation.txt +++ b/docs/documentation.txt @@ -12,7 +12,7 @@ ifdef::website[] - NUT User Manual (link:docs/user-manual.chunked/index.html[online]) (link:docs/user-manual.pdf[PDF]) - Cables information (link:cables.html[online]) (link:docs/cables.pdf[PDF]) - link:docs/man/index.html#User_man[User manual pages] -- link:ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported +- link:ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported; see also link:stable-hcl.html[the HCL] - link:docs/solaris-usb.html[Notes on NUT monitoring of USB devices in Solaris and related operating systems] endif::website[] ifndef::website[] @@ -20,7 +20,7 @@ ifndef::website[] - linkdoc:user-manual[NUT user manual] - <> - link:../man/index.html#User_man[User manual pages] -- link:http://www.networkupstools.org/ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported +- link:https://www.networkupstools.org/ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported; see also link:https://www.networkupstools.org/stable-hcl.html[the HCL] - link:../solaris-usb.html[Notes on NUT monitoring of USB devices in Solaris and related operating systems] endif::website[] - link:https://github.com/networkupstools/ConfigExamples/releases/latest[NUT Configuration Examples] book maintained by Roger Price From 1b22b5bbbe5d75e7f8430e521c43da88425c5dc3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 26 May 2023 12:34:16 +0200 Subject: [PATCH 0809/1232] docs/documentation.txt: refer to NUT GitHub Wiki --- docs/documentation.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/documentation.txt b/docs/documentation.txt index 7abd099f7e..101218eb15 100644 --- a/docs/documentation.txt +++ b/docs/documentation.txt @@ -24,6 +24,7 @@ ifndef::website[] - link:../solaris-usb.html[Notes on NUT monitoring of USB devices in Solaris and related operating systems] endif::website[] - link:https://github.com/networkupstools/ConfigExamples/releases/latest[NUT Configuration Examples] book maintained by Roger Price +- link:https://github.com/networkupstools/nut/wiki[NUT GitHub Wiki] Developer Documentation ----------------------- From ec74af905dfac5ff774add1e366d7d19eb40cba1 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Thu, 1 Jun 2023 06:20:37 +0200 Subject: [PATCH 0810/1232] tools/gitlog2changelog.py: fix bitwise AND into regular AND Several if conditions where using bitwise AND whereas the intent was to do a regular AND test. --- tools/gitlog2changelog.py.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 5eeb06c497..9ec25a7a97 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -114,7 +114,7 @@ for line in fin: elif "Signed-off-by" in line: continue # Extract the actual commit message for this commit - elif authorFound & dateFound & messageFound is False: + elif authorFound and dateFound and messageFound is False: # Find the commit message if we can if len(line) == fin_chop: if messageNL: @@ -133,7 +133,7 @@ for line in fin: filesFound = True continue # Collect the files for this commit. FIXME: Still need to add +/- to files - elif authorFound & dateFound & messageFound: + elif authorFound and dateFound and messageFound: fileList = re.split(r' \| ', line, 2) if len(fileList) > 1: if len(files) > 0: @@ -141,7 +141,7 @@ for line in fin: else: files = fileList[0].strip() # All of the parts of the commit have been found - write out the entry - if authorFound & dateFound & messageFound & filesFound: + if authorFound and dateFound and messageFound and filesFound: # First the author line, only outputted if it is the first for that # author on this day authorLine = date + " " + author From f236b5e60837680223af83ff8c69460f862eba52 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Jun 2023 11:47:35 +0200 Subject: [PATCH 0811/1232] NEWS: published new maintainer GPG key DE0184DA7043DCF7 [#1410] --- NEWS | 14 ++++++++++++++ docs/nut.dict | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 4708266258..c2f5017ff1 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,20 @@ https://github.com/networkupstools/nut/milestone/8 https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=3493 (even though this RFC is not formally an Internet Standard) + - Published a new maintainer GPG key to sign tags and release artifacts, + and possibly git commits as well, as part of solution for issue #1410. + You can pull it from common OpenPGP servers with the following command: ++ +---- +:; gpg --recv-key DE0184DA7043DCF7 +gpg: key DE0184DA7043DCF7: public key "Jim Klimov (Doing FOSS + since last millennium) " imported +gpg: Total number processed: 1 +gpg: imported: 1 +---- ++ +as part of https://github.com/networkupstools/nut/issues/1410 solution. + - Bug fixes for fallout possible due to "fightwarn" effort and other evolution in NUT v2.8.0 release: * The `upsdebugx()` and similar methods were converted to macros in #685 diff --git a/docs/nut.dict b/docs/nut.dict index aeb8f9aa10..fb332a7b8b 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3174 utf-8 +personal_ws-1.1 en 3175 utf-8 AAS ABI ACFAIL @@ -239,6 +239,7 @@ Cygwin DATACABLE DATAPATH DCE +DCF DDD DDDDD DDDDDD From 855e8accdf36c3d220090ae7488f2b58b4a869fe Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 1 Jun 2023 16:35:58 +0200 Subject: [PATCH 0812/1232] docs/nut.dict: update with OpenPGP [#1410] --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index fb332a7b8b..f37f281e5e 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3175 utf-8 +personal_ws-1.1 en 3176 utf-8 AAS ABI ACFAIL @@ -836,6 +836,7 @@ OnTmDays OneAC OpenBSD OpenIndiana +OpenPGP OpenSSL OpenSolaris OpenSource From 74d2ade4d24ab0f78e4d0ab17e9a7dc560830d00 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Jun 2023 12:14:15 +0200 Subject: [PATCH 0813/1232] tools/gitlog2changelog.py.in: update TextWrapper settings to not break up file paths Follows up from #1945 --- tools/gitlog2changelog.py.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 9ec25a7a97..12b80ad3e0 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -69,7 +69,8 @@ messageNL = False files = "" prevAuthorLine = "" -wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t ") +# See also: https://github.com/python/cpython/blob/main/Lib/textwrap.py +wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t ", break_on_hyphens=False, break_long_words=False) # The main part of the loop for line in fin: From 7d96fb5229ad03e09d40d579de27f74429d7111f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 2 Jun 2023 13:22:55 +0200 Subject: [PATCH 0814/1232] NEWS, UPGRADING: make note that ChangeLog file markup will differ from that in older NUT releases [#1955] --- NEWS | 5 +++++ UPGRADING | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/NEWS b/NEWS index c2f5017ff1..7b0421b589 100644 --- a/NEWS +++ b/NEWS @@ -352,6 +352,11 @@ and a `driver.killpower` instant command (for safety, must be unlocked by - The `COPYING` file was updated with licenses and attribution for certain source code files and blocks coming from the Internet originally [#1758] + - The `tools/gitlog2changelog.py.in` script was revised, in particular to + generate the `ChangeLog` file more consistently with different versions + of Python interpreter, and without breaking the long file paths in the + resulting mark-up text [#1945, #1955] + --------------------------------------------------------------------------- Release notes for NUT 2.8.0 - what's new since 2.7.4: diff --git a/UPGRADING b/UPGRADING index ca424d6916..10b87c0968 100644 --- a/UPGRADING +++ b/UPGRADING @@ -112,6 +112,14 @@ Changes from 2.8.0 to 2.8.1 were renamed: `pw` is now `eaton_pw_nm2`, and `pxgx_ups` is `eaton_pxg_ups` [#1715] +- The `tools/gitlog2changelog.py.in` script was revised, in particular to + generate the `ChangeLog` file more consistently with different versions + of Python interpreter, and without breaking the long file paths in the + resulting mark-up text. Due to this, a copy of this file distributed with + NUT release archives is expected to considerably differ on first glance + from its earlier released versions (not just adding lines for the new + release, but changing lines in the older releases too) [#1945, #1955] + Changes from 2.7.4 to 2.8.0 --------------------------- From 731b1dad0ba253027065a6cf6a9c6ff1f03c9874 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 5 Jun 2023 11:24:34 +0200 Subject: [PATCH 0815/1232] docs/new-drivers.txt: add anchor for _status_data [#1957] --- docs/new-drivers.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index 1174d71789..00fff25540 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -207,6 +207,7 @@ what it can do. dstate_setflags("input.transfer.high", ST_FLAG_RW); +[[_status_data]] Status data ~~~~~~~~~~~ From fdd580442738668a024b1c366f1e85afc9ed82b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 5 Jun 2023 11:30:03 +0200 Subject: [PATCH 0816/1232] docs/man/upslog.txt: refer to documentation on supported variable names [#1957] --- docs/man/upslog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/man/upslog.txt b/docs/man/upslog.txt index a35f89baa1..882a13549c 100644 --- a/docs/man/upslog.txt +++ b/docs/man/upslog.txt @@ -47,6 +47,9 @@ within this string are: %PID%;; insert the pid of upslog %VAR varname%;; insert the value of variable varname +(see NUT developer documentation chapter "Variables" on-line or in +the `docs/nut-names.txt` file in sources of the NUT version you have +installed for more details) The default format string is: From e312277871e308d1e718d0d36abdbce25b4f9b89 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 5 Jun 2023 12:46:00 +0200 Subject: [PATCH 0817/1232] docs/new-drivers.txt, docs/nut-names.txt: no need for custom anchor for _status_data, change link style instead [#1957] --- docs/new-drivers.txt | 1 - docs/nut-names.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index 00fff25540..1174d71789 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -207,7 +207,6 @@ what it can do. dstate_setflags("input.transfer.high", ST_FLAG_RW); -[[_status_data]] Status data ~~~~~~~~~~~ diff --git a/docs/nut-names.txt b/docs/nut-names.txt index 12f0f526c8..1ee50b0e01 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -116,7 +116,7 @@ ups: General unit information [options="header"] |=============================================================================== | Name | Description | Example value -| ups.status | UPS status | linkdoc:developer-guide[OL,_status_data] +| ups.status | UPS status | <<_status_data,OL>> | ups.alarm | UPS alarms | OVERHEAT | ups.time | Internal UPS clock time (opaque string) | 12:34 From 8a1d532db04cd2d35a547b3135082a90c3b005ae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 8 Jun 2023 09:13:49 +0200 Subject: [PATCH 0818/1232] docs/download.txt: update references to NUT client for VMware ESXi And link to NUT Wiki for further setup suggestions --- docs/download.txt | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/download.txt b/docs/download.txt index 8cd0fc252a..8f27fbba5b 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -186,7 +186,25 @@ Virtualization packages VMware ~~~~~~ -- NUT client 2.7.4 for ESXi 5.0, 5.1, 5.5 and 6.0 (offsite, René Garcia) - - * link:http://rene.margar.fr/2012/05/client-nut-pour-esxi-5-0/[blog entry (French)] - * link:http://rene.margar.fr/downloads/NutClient-ESXi500-1.4.0.tar.gz[VIB package (v1.4.0)] +- NUT client for VMware ESXi (several versions of both, offsite, René Garcia). + Since the hypervisor manager environment lacks access to hardware ports, this + package only includes the `upsmon` client integration, and a NUT server must + run in a VM with passed-through ports. ++ + See link:https://github.com/networkupstools/nut/wiki/NUT-and-VMware-(ESXi)[NUT + and VMware (ESXi) page on NUT Wiki] for more community-contributed details. ++ + Note that the VIB package versioning is independent of NUT or VMware versions, + they are however mentioned in downloadable file names. As of this writing, + there are builds spanning VMware ESXi 5.0-8.0 and NUT 2.7.4-2.8.0: + + * link:https://github.com/rgc2000/NutClient-ESXi[GitHub repository with build recipes], + including link:https://github.com/rgc2000/NutClient-ESXi/releases[binary releases] + * link:https://rene.margar.fr/2012/05/client-nut-pour-esxi-5-0/[Original blog entry (French)] + * link:https://rene.margar.fr/2012/05/client-nut-pour-esxi-5-0/comment-page-22/#comment-13325[Historic + details of the recipe evolution] + * link:https://rene.margar.fr/downloads/NutClient-ESXi500-1.4.0.tar.gz[VIB package + (in fact automatically redirects to latest build)] + +WARNING: This module is provided "as is" and is not approved by VMware, +you may lose VMware support if you install it. Use it at your own risks. From b783c00f5e63a5a480d62b65450e8c0fc9cb69b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 8 Jun 2023 09:24:32 +0200 Subject: [PATCH 0819/1232] NEWS: update with reference to NUT client for VMware ESXi" project on GitHub [#1961] --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 7b0421b589..f70ba0120c 100644 --- a/NEWS +++ b/NEWS @@ -357,6 +357,10 @@ and a `driver.killpower` instant command (for safety, must be unlocked by of Python interpreter, and without breaking the long file paths in the resulting mark-up text [#1945, #1955] + - The "NUT client for VMware ESXi" project (by René Garcia) got its build + recipes published on GitHub at https://github.com/rgc2000/NutClient-ESXi + [#1961] + --------------------------------------------------------------------------- Release notes for NUT 2.8.0 - what's new since 2.7.4: From 9a99eff90052ddf83706d868142c3692ae63614d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 8 Jun 2023 10:20:25 +0200 Subject: [PATCH 0820/1232] docs/download.txt: update references to NUT client for VMWare ESXi - fix asciidoc markup [#1961] --- docs/download.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/download.txt b/docs/download.txt index 8f27fbba5b..362fc3391f 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -191,12 +191,15 @@ VMware package only includes the `upsmon` client integration, and a NUT server must run in a VM with passed-through ports. + - See link:https://github.com/networkupstools/nut/wiki/NUT-and-VMware-(ESXi)[NUT +See link:https://github.com/networkupstools/nut/wiki/NUT-and-VMware-(ESXi)[NUT and VMware (ESXi) page on NUT Wiki] for more community-contributed details. + - Note that the VIB package versioning is independent of NUT or VMware versions, +Note that the VIB package versioning is independent of NUT or VMware versions, they are however mentioned in downloadable file names. As of this writing, - there are builds spanning VMware ESXi 5.0-8.0 and NUT 2.7.4-2.8.0: + there are builds spanning VMware ESXi 5.0-8.0 and NUT 2.7.4-2.8.0. ++ +WARNING: This module is provided "as is" and is not approved by VMware, +you may lose VMware support if you install it. Use it at your own risks. * link:https://github.com/rgc2000/NutClient-ESXi[GitHub repository with build recipes], including link:https://github.com/rgc2000/NutClient-ESXi/releases[binary releases] @@ -205,6 +208,3 @@ VMware details of the recipe evolution] * link:https://rene.margar.fr/downloads/NutClient-ESXi500-1.4.0.tar.gz[VIB package (in fact automatically redirects to latest build)] - -WARNING: This module is provided "as is" and is not approved by VMware, -you may lose VMware support if you install it. Use it at your own risks. From 6cd6b5676957b9c77c94328e259358ce0d9b67a2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 8 Jun 2023 10:21:25 +0200 Subject: [PATCH 0821/1232] docs/download.txt: update references to NUT client for VMWare ESXi - fix wording [#1961] --- docs/download.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/download.txt b/docs/download.txt index 362fc3391f..302426e78d 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -186,7 +186,7 @@ Virtualization packages VMware ~~~~~~ -- NUT client for VMware ESXi (several versions of both, offsite, René Garcia). +- NUT client for VMware ESXi (several versions of both; offsite, by René Garcia). Since the hypervisor manager environment lacks access to hardware ports, this package only includes the `upsmon` client integration, and a NUT server must run in a VM with passed-through ports. From e4b103a9b22b188a738555cbdc33a1bb2ab9f213 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 17:58:22 +0200 Subject: [PATCH 0822/1232] tests/NIT/nit.sh: typo fix --- 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 8b746f7af7..7debf2e178 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -876,7 +876,7 @@ testcase_sandbox_start_drivers_after_upsd() { } testcase_sandbox_upsc_query_model() { - loginfo "[testcase_sandbox_upsc_query_model] Query model from dummy device" + log_info "[testcase_sandbox_upsc_query_model] Query model from dummy device" runcmd upsc dummy@localhost:$NUT_PORT device.model || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" if [ x"$CMDOUT" != x"Dummy UPS" ] ; then log_error "got this reply for upsc query when 'Dummy UPS' was expected: $CMDOUT" From 7c28adb56ce8ee1c2c4709ded18f887fb1de58fd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 11:24:03 +0200 Subject: [PATCH 0823/1232] clients/upssched.c: improve logging of client connection life cycle --- clients/upssched.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index cbf84abac3..204da32a85 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -620,7 +620,7 @@ static TYPE_FD conn_add(TYPE_FD sockfd) else connhead = conn; - upsdebugx(3, "new connection on fd %p", acc); + upsdebugx(3, "new connection on handle %p", acc); pconf_init(&conn->ctx, NULL); #endif @@ -687,7 +687,7 @@ static int sock_read(conn_t *conn) return 0; /* O_NDELAY with zero bytes means nothing to read but - * since read() follows a succesful select() with + * since read() follows a successful select() with * ready file descriptor, ret shouldn't be 0. */ if (ret == 0) continue; @@ -821,6 +821,8 @@ static void start_daemon(TYPE_FD lockfd) close(lockfd); /* now watch for activity */ + upsdebugx(2, "Timer daemon waiting for connections on pipefd %d", + pipefd); for (;;) { /* wait at most 1s so we can check our timers regularly */ @@ -842,7 +844,6 @@ static void start_daemon(TYPE_FD lockfd) ret = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (ret > 0) { - if (FD_ISSET(pipefd, &rfds)) conn_add(pipefd); @@ -853,6 +854,7 @@ static void start_daemon(TYPE_FD lockfd) if (FD_ISSET(tmp->fd, &rfds)) { if (sock_read(tmp) < 0) { + upsdebugx(3, "closing connection on fd %d", tmp->fd); close(tmp->fd); conn_del(tmp); } @@ -937,6 +939,7 @@ static void start_daemon(TYPE_FD lockfd) else { if( tmp != NULL) { if (sock_read(tmp) < 0) { + upsdebugx(3, "closing connection on handle %p", tmp->fd); CloseHandle(tmp->fd); conn_del(tmp); } @@ -1449,6 +1452,7 @@ int main(int argc, char **argv) /* see if this matches anything in the config file */ /* This is actually the processing loop: * checkconf -> conf_arg -> parse_at -> sendcmd -> daemon if needed + * -> start_daemon -> conn_add(pipefd) or sock_read(conn) */ checkconf(); From 2b8f4765f0fc74ea9762fe0a85e2405c70ee5202 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 16:07:48 +0200 Subject: [PATCH 0824/1232] clients/upssched.c: log-trace when the process (daemon or CLI) exits --- clients/upssched.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clients/upssched.c b/clients/upssched.c index 204da32a85..bb9ce9af05 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -170,6 +170,7 @@ static void checktimers(void) sleep(15); #endif + upsdebugx(1, "Timer queue empty, closing pipe and exiting upssched daemon"); unlink(pipefn); exit(EXIT_SUCCESS); } @@ -1444,7 +1445,7 @@ int main(int argc, char **argv) notify_type = getenv("NOTIFYTYPE"); if ((!upsname) || (!notify_type)) { - printf("Error: UPSNAME and NOTIFYTYPE must be set.\n"); + printf("Error: environment variables UPSNAME and NOTIFYTYPE must be set.\n"); printf("This program should only be run from upsmon.\n"); exit(EXIT_FAILURE); } @@ -1456,5 +1457,6 @@ int main(int argc, char **argv) */ checkconf(); + upsdebugx(1, "Exiting upssched (CLI process)"); exit(EXIT_SUCCESS); } From df5da23383fba09f00de7ded3aa05c3ac57bed7e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 16:10:56 +0200 Subject: [PATCH 0825/1232] clients/upssched.c: do not close STDERR of the daemon (to re-open as /dev/null) when nut_debug_level!=0 (follow-up from [#1879, #1889]) --- clients/upssched.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index bb9ce9af05..4a14d06769 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -775,8 +775,13 @@ static void start_daemon(TYPE_FD lockfd) fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDIN"); if (dup2(devnull, STDOUT_FILENO) != STDOUT_FILENO) fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); - if (dup2(devnull, STDERR_FILENO) != STDERR_FILENO) - fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + + if (nut_debug_level) { + upsdebugx(1, "Keeping stderr open due to debug verbosity %d", nut_debug_level); + } else { + if (dup2(devnull, STDERR_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + } close(devnull); } @@ -791,9 +796,13 @@ static void start_daemon(TYPE_FD lockfd) if (dup(STDIN_FILENO) != STDOUT_FILENO) fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDOUT"); - close(STDERR_FILENO); - if (dup(STDIN_FILENO) != STDERR_FILENO) - fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDERR"); + if (nut_debug_level) { + upsdebugx(1, "Keeping stderr open due to debug verbosity %d", nut_debug_level); + } else { + close(STDERR_FILENO); + if (dup(STDIN_FILENO) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "dup /dev/null as STDERR"); + } # else close(STDIN_FILENO); if (open("/dev/null", O_RDWR) != STDIN_FILENO) @@ -803,9 +812,13 @@ static void start_daemon(TYPE_FD lockfd) if (open("/dev/null", O_RDWR) != STDOUT_FILENO) fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDOUT"); - close(STDERR_FILENO); - if (open("/dev/null", O_RDWR) != STDERR_FILENO) - fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + if (nut_debug_level) { + upsdebugx(1, "Keeping stderr open due to debug verbosity %d", nut_debug_level); + } else { + close(STDERR_FILENO); + if (open("/dev/null", O_RDWR) != STDERR_FILENO) + fatal_with_errno(EXIT_FAILURE, "re-open /dev/null as STDERR"); + } # endif #endif From 55d7c3fcc4d11a0267d5a530b454a2ae7b0ab47f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 17:00:51 +0200 Subject: [PATCH 0826/1232] clients/upssched.c: if we consistently get read()==0, abort eventually (even if no formal errors are reported) [#1964] --- clients/upssched.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index 4a14d06769..b0434ef151 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -49,6 +49,7 @@ #include #include #include +#include #else #include "wincompat.h" #include @@ -679,8 +680,13 @@ static int sock_read(conn_t *conn) for (i = 0; i < US_MAX_READ; i++) { #ifndef WIN32 + errno = 0; ret = read(conn->fd, &ch, 1); + if (ret > 0) + upsdebugx(6, "read() from fd %d returned %" PRIiSIZE " (bytes): '%c'; errno=%d: %s", + conn->fd, ret, ch, errno, strerror(errno)); + if (ret < 1) { /* short read = no parsing, come back later */ @@ -689,9 +695,37 @@ static int sock_read(conn_t *conn) /* O_NDELAY with zero bytes means nothing to read but * since read() follows a successful select() with - * ready file descriptor, ret shouldn't be 0. */ - if (ret == 0) + * ready file descriptor, ret shouldn't be 0. + * This may also mean that the counterpart has exited + * and the file descriptor should be reaped. + */ + if (ret == 0) { + struct pollfd pfd; + pfd.fd = conn->fd; + pfd.events = 0; + pfd.revents = 0; + /* Note: we check errno twice, since it could + * have been set by read() above or by one + * of the probing routines below + */ + if (errno + || (fcntl(conn->fd, F_GETFD) < 0) + || (poll(&pfd, 1, 0) <= 0) + || errno + ) { + upsdebugx(4, "read() from fd %d returned 0; errno=%d: %s", + conn->fd, errno, strerror(errno)); + return -1; /* connection closed, probably */ + } + if (i == (US_MAX_READ - 1)) { + upsdebugx(4, "read() from fd %d returned 0 " + "too many times in a row, aborting " + "sock_read(); errno=%d: %s", + conn->fd, errno, strerror(errno)); + return -1; /* connection closed, probably */ + } continue; + } /* some other problem */ return -1; /* error */ @@ -733,6 +767,9 @@ static int sock_read(conn_t *conn) return 1; /* we did some work */ } + upsdebugx(6, "sock_read() from fd %d returned nothing; errno=%d: %s", + conn->fd, errno, strerror(errno)); + return 0; /* fell out without parsing anything */ } From c94c7e14c7fd40c9e3d6e1ec766c65f4a059e630 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 17:31:52 +0200 Subject: [PATCH 0827/1232] clients/upssched.c: start_daemon() loop (POSIX builds): generally throttle in case we have empty sock_read()s [#1964] --- clients/upssched.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/clients/upssched.c b/clients/upssched.c index b0434ef151..eb8df4d232 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -876,6 +876,11 @@ static void start_daemon(TYPE_FD lockfd) pipefd); for (;;) { + int zero_reads = 0, total_reads = 0; + struct timeval start, now; + + gettimeofday(&start, NULL); + /* wait at most 1s so we can check our timers regularly */ tv.tv_sec = 1; tv.tv_usec = 0; @@ -904,11 +909,15 @@ static void start_daemon(TYPE_FD lockfd) tmpnext = tmp->next; if (FD_ISSET(tmp->fd, &rfds)) { - if (sock_read(tmp) < 0) { + total_reads++; + ret = sock_read(tmp); + if (ret < 0) { upsdebugx(3, "closing connection on fd %d", tmp->fd); close(tmp->fd); conn_del(tmp); } + if (ret == 0) + zero_reads++; } tmp = tmpnext; @@ -916,6 +925,30 @@ static void start_daemon(TYPE_FD lockfd) } checktimers(); + + /* upsdebugx(6, "zero_reads=%d total_reads=%d", zero_reads, total_reads); */ + if (zero_reads && zero_reads == total_reads) { + /* Catch run-away loops - that is, consider + * throttling the cycle as to not hog CPU: + * did select() spend its second to reply, + * or had something to say immediately? + * Note that while select() may have changed + * "tv" to deduct the time waited, our further + * processing loops could eat some more time. + * So we just check the difference of "start" + * and "now". If we did spend a substantial + * part of the second, do not delay further. + */ + double d; + gettimeofday(&now, NULL); + d = difftimeval(now, start); + upsdebugx(6, "difftimeval() => %f sec", d); + if (d > 0 && d < 0.2) { + d = (1.0 - d) * 1000000.0; + upsdebugx(5, "Enforcing a throttling sleep: %f usec", d); + usleep(d); + } + } } #else /* WIN32 */ From 5339f460ca816435e5720f02a047243d099cf306 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 17:46:41 +0200 Subject: [PATCH 0828/1232] NEWS, docs/man/upssched.txt, clients/upssched.c: warn that enabled debug remains noisy for daemon part too [#1965] --- NEWS | 2 ++ clients/upssched.c | 2 +- docs/man/upssched.txt | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f70ba0120c..3087ebed64 100644 --- a/NEWS +++ b/NEWS @@ -300,6 +300,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. honour a `NUT_DEBUG_LEVEL=NUM` environment variable if no `-D` arguments were provided. Unlike those arguments, the environment variable does not enforce that daemons run in foreground mode by default [#1915] + * Note that unlike some other NUT daemons, `upssched` with enabled + debug does not stop reporting on `stderr`! [#1965] - Implemented generic support for INSTCMD and SETVAR use-cases shared by all drivers, and in particular to see and change active debug verbosity diff --git a/clients/upssched.c b/clients/upssched.c index eb8df4d232..c107c34331 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -1474,7 +1474,7 @@ static void help(const char *arg_progname) printf("Practical behavior is managed by UPSNAME and NOTIFYTYPE envvars\n"); printf("\nUsage: %s [OPTIONS]\n\n", arg_progname); - printf(" -D raise debugging level\n"); + printf(" -D raise debugging level (NOTE: keeps reporting when daemonized)\n"); printf(" -V display the version of this software\n"); printf(" -h display this help\n"); diff --git a/docs/man/upssched.txt b/docs/man/upssched.txt index 3c582fc719..b5830701f9 100644 --- a/docs/man/upssched.txt +++ b/docs/man/upssched.txt @@ -108,6 +108,11 @@ ENVIRONMENT VARIABLES were provided on command line, but does not request that the daemon runs in foreground mode. +NOTE: Unlike some other NUT daemons, `upssched` with enabled debug +does not stop reporting on `stderr`! It forks a background process +with the first call as an event handler, which exits soon after all +tracked timers have elapsed and were handled (if needed). + *UPSNAME* and *NOTIFYTYPE* are required, as detailed above. They are set by `upsmon` when it calls `upssched` as its choice of `NOTIFYCMD`. From 6a12ba53fc8b1380fd5a75027dddfe40f1c5d765 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 13 Jun 2023 17:53:31 +0200 Subject: [PATCH 0829/1232] NEWS: upssched CPU burn fixed [#1965, #1964] --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 3087ebed64..5aa7bbb2e4 100644 --- a/NEWS +++ b/NEWS @@ -303,6 +303,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * Note that unlike some other NUT daemons, `upssched` with enabled debug does not stop reporting on `stderr`! [#1965] + - A bug in `upssched` was discovered and fixed, where it ran a tight loop + stressing the CPU; it was presumably introduced between NUT v2.7.4 and + v2.8.0 releases [#1964, #1965] + - Implemented generic support for INSTCMD and SETVAR use-cases shared by all drivers, and in particular to see and change active debug verbosity using the driver-server and server-client protocol (at higher priority From 577a7ad7cf9842b83605be40c0ff0fa0b68e479d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 14 Jun 2023 16:23:57 +0200 Subject: [PATCH 0830/1232] clients/upssched.c: add enter/exit log tracing of sock_read() [#1964] --- clients/upssched.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/clients/upssched.c b/clients/upssched.c index c107c34331..4b8e9c4ba9 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -677,8 +677,12 @@ static int sock_read(conn_t *conn) ssize_t ret; char ch; + upsdebugx(6, "Starting sock_read()"); for (i = 0; i < US_MAX_READ; i++) { - + /* NOTE: This does not imply that each command line must + * fit in the US_MAX_READ length limit - at worst we would + * "return 0", and continue with pconf_char() next round. + */ #ifndef WIN32 errno = 0; ret = read(conn->fd, &ch, 1); @@ -690,8 +694,10 @@ static int sock_read(conn_t *conn) if (ret < 1) { /* short read = no parsing, come back later */ - if ((ret == -1) && (errno == EAGAIN)) + if ((ret == -1) && (errno == EAGAIN)) { + upsdebugx(6, "Ending sock_read(): short read"); return 0; + } /* O_NDELAY with zero bytes means nothing to read but * since read() follows a successful select() with @@ -728,6 +734,7 @@ static int sock_read(conn_t *conn) } /* some other problem */ + upsdebugx(6, "Ending sock_read(): some other problem"); return -1; /* error */ } #else @@ -755,10 +762,14 @@ static int sock_read(conn_t *conn) upslogx(LOG_NOTICE, "Parse error on sock: %s", conn->ctx.errmsg); + upsdebugx(6, "Ending sock_read(): parse error"); return 0; /* nothing parsed */ } /* try to use it, and complain about unknown commands */ + upsdebugx(3, "Ending sock_read() on a good note: try to use command:"); + for (size_t numarg = 0; numarg < conn->ctx.numargs; numarg++) + upsdebugx(3, "\targ %" PRIuSIZE ": %s", numarg, conn->ctx.arglist[numarg]); if (!sock_arg(conn)) { log_unknown(conn->ctx.numargs, conn->ctx.arglist); send_to_one(conn, "ERR UNKNOWN\n"); @@ -767,7 +778,9 @@ static int sock_read(conn_t *conn) return 1; /* we did some work */ } - upsdebugx(6, "sock_read() from fd %d returned nothing; errno=%d: %s", + upsdebugx(6, "sock_read() from fd %d returned nothing " + "(maybe still collecting the command line); " + "errno=%d: %s", conn->fd, errno, strerror(errno)); return 0; /* fell out without parsing anything */ From 02eea9cbc65f23489508bf07b1c7764b711c5b4a Mon Sep 17 00:00:00 2001 From: Blaz Zakrajsek Date: Fri, 16 Jun 2023 22:43:49 +0200 Subject: [PATCH 0831/1232] Improve liebert-hid driver - Add additional properties by analyzing the HID descriptor of the PowerWalker VI 1200 SHL - Existing properties were kept as they are to avoid breakage with other devices using the same driver --- drivers/liebert-hid.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/liebert-hid.c b/drivers/liebert-hid.c index 1ec525286e..3b2120d6bf 100644 --- a/drivers/liebert-hid.c +++ b/drivers/liebert-hid.c @@ -5,6 +5,7 @@ * 2005 - 2006 Peter Selinger * 2007 Charles Lepple * 2018 Markus "Links2004" + * 2023 Blaž Zakrajšek * * 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 @@ -71,28 +72,43 @@ static hid_info_t liebert_hid2nut[] = { #if WITH_UNMAPPED_DATA_POINTS { "unmapped.ups.powersummary.flowid", 0, 0, "UPS.PowerSummary.FlowID", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, - { "unmapped.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, { "unmapped.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.product", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", 0, stringid_conversion }, { "unmapped.ups.powersummary.imanufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.manufacturer", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%s", 0, stringid_conversion }, + { "unmapped.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%.0f", 0, NULL }, + { "unmapped.ups.powersummary.serialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", 0, stringid_conversion }, #endif /* if WITH_UNMAPPED_DATA_POINTS */ + /* Battery page */ { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.2f", 0, NULL }, - { "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.2f", HU_FLAG_STATIC, NULL }, { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL }, + { "battery.charge.capacity.design", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, + { "battery.charge.capacity.remaining", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion }, - { "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL }, + /* UPS page */ + { "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL }, + { "ups.power.nominal", 0, 0, "UPS.Flow.[4].ConfigApparentPower", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "ups.test.result", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "%s", 0, test_read_info }, + + { "ups.beeper.status", 0 ,0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", HU_FLAG_SEMI_STATIC, beeper_info }, + + /* Output page */ { "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.1f", 0, NULL }, + { "output.voltage.nominal", 0, 0, "UPS.Flow.[4].ConfigVoltage", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, { "output.frequency", 0, 0, "UPS.PowerConverter.Output.Frequency", NULL, "%.2f", 0, NULL }, + { "output.frequency.nominal", 0, 0, "UPS.Flow.[4].ConfigFrequency", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, { "output.transfer.high", 0, 0, "UPS.PowerConverter.Output.HighVoltageTransfer", NULL, "%.1f", HU_FLAG_SEMI_STATIC, NULL }, { "output.transfer.low", 0, 0, "UPS.PowerConverter.Output.LowVoltageTransfer", NULL, "%.1f", HU_FLAG_SEMI_STATIC, NULL }, + /* Input page */ { "input.voltage", 0, 0, "UPS.PowerConverter.Input.[1].Voltage", NULL, "%.1f", 0, NULL }, { "input.frequency", 0, 0, "UPS.PowerConverter.Input.[1].Frequency", NULL, "%.2f", 0, NULL }, @@ -101,12 +117,28 @@ static hid_info_t liebert_hid2nut[] = { { "input.frequency.transfer.low", 0, 0, "UPS.PowerConverter.Output.ffff00f9", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, { "input.frequency.transfer.high", 0, 0, "UPS.PowerConverter.Output.ffff00f8", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL}, + /* Status page */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, "%.0f", HU_FLAG_QUICK_POLL, online_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, "%.0f", HU_FLAG_QUICK_POLL, lowbatt_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, "%.0f", HU_FLAG_QUICK_POLL, charging_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, "%.0f", HU_FLAG_QUICK_POLL, discharging_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, "%.0f", 0, overload_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, "%.0f", 0, shutdownimm_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, "%.0f", HU_FLAG_QUICK_POLL, overload_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, HU_FLAG_QUICK_POLL, off_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, NULL, HU_FLAG_QUICK_POLL, commfault_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, "%.0f", HU_FLAG_QUICK_POLL, shutdownimm_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Buck", NULL, NULL, 0, trim_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Boost", NULL, NULL, 0, boost_info }, + + /* Variables */ + { "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}, + + /* Instant commands */ + { "test.battery.start", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL }, + { "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 }, + { "beeper.toggle", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL }, /* end of structure. */ { NULL, 0, 0, NULL, NULL, NULL, 0, NULL } From ff36202eed8ef5b35485df4b0ab17443f409c4cf Mon Sep 17 00:00:00 2001 From: Blaz Zakrajsek Date: Sat, 17 Jun 2023 21:28:57 +0200 Subject: [PATCH 0832/1232] Apply code review fixes - Replace non-standard variable names for Full charge capacity and Design capacity - Prefix with experimental --- drivers/liebert-hid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/liebert-hid.c b/drivers/liebert-hid.c index 3b2120d6bf..7b87706fc5 100644 --- a/drivers/liebert-hid.c +++ b/drivers/liebert-hid.c @@ -86,8 +86,8 @@ static hid_info_t liebert_hid2nut[] = { /* Battery page */ { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.2f", 0, NULL }, { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL }, - { "battery.charge.capacity.design", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, - { "battery.charge.capacity.remaining", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, + { "experimental.battery.capacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, + { "experimental.battery.capacity.nominal", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion }, From d10bbe58c722c8d44396304b5e81a8801e145c53 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 18 Jun 2023 16:17:21 +0200 Subject: [PATCH 0833/1232] docs/nut-names.txt: reference `docs/new-drivers.txt` by name for device status data definitions --- docs/nut-names.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index 1ee50b0e01..873fe09c64 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -18,7 +18,15 @@ as used in commands and messages between the Attachment Daemon (the `upsd` in case of NUT implementation of the standard) and the clients. ==== -This document defines the standard names of NUT commands and variables. +This document defines the standard names of NUT commands and variables +(not to be confused with <<_status_data,device status data>> described in +ifdef::website[] +another chapter). +endif::website[] +ifndef::website[] +the `docs/new-drivers.txt` in NUT source codebase). +endif::website[] + Developers should use the names recorded here, with dstate functions and data mappings provided in NUT drivers for interactions with power devices. From 15149756d70b244f120978fecdb400844e0e3d19 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Jun 2023 11:35:40 +0200 Subject: [PATCH 0834/1232] docs/maintainer-guide.txt: stress the release git tag rituals [#1971] --- docs/maintainer-guide.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index 62269bbe94..ea5d5e6794 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -82,6 +82,9 @@ SANDBOX (to be completed and pushed) * update version to (ex: 2.7.3) in nut/configure.ac * create a GPG-signed tag v (ex: v2.7.3) +** try to avoid adding signed tags later (ex. v2.8.0-signed) to avoid the + mess in GitHub release URLs (or do amend that post-factum), for more + details see e.g. https://github.com/networkupstools/nut/issues/1971 * `make dist` * maybe update nut/configure.ac version to .1 (ex: 2.7.3.1) * push commits and tag From 05b7ec52c21295369d284b4cb57fa1165eb1664b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jun 2023 12:29:24 +0200 Subject: [PATCH 0835/1232] docs/man/nut-scanner.txt, docs/man/snmp-ups.txt: clarify that `secLevel` is required to use non-trivial authentication [#734] --- docs/man/nut-scanner.txt | 1 + docs/man/snmp-ups.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index cf77596bfd..543e2f2ced 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -126,6 +126,7 @@ SNMP V3 OPTIONS *-l* | *--secLevel* 'security level':: Set the 'security level' used for SNMPv3 messages. Allowed values are: noAuthNoPriv, authNoPriv and authPriv. +This parameter is mandatory if you use non-trivial authentication. *-u* | *--secName* 'security name':: Set the 'security name' used for authenticated SNMPv3 messages. diff --git a/docs/man/snmp-ups.txt b/docs/man/snmp-ups.txt index a37452205e..0f5f74cd0d 100644 --- a/docs/man/snmp-ups.txt +++ b/docs/man/snmp-ups.txt @@ -136,6 +136,7 @@ equipment which has strangeness in the three-phase power reporting. *secLevel*='value':: Set the securityLevel used for SNMPv3 messages (default=noAuthNoPriv, allowed: authNoPriv,authPriv) +This parameter is mandatory if you use non-trivial authentication. *secName*='value':: Set the securityName used for authenticated SNMPv3 messages (no default) From aca017ff3999e3846701766e7e1958310230d89d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 15:31:49 +0200 Subject: [PATCH 0836/1232] Bump all driver versions before NUT v2.8.1 release [#1951] Follow-up after core driver changes (main.c etc.) with `driver.state` #1767, driver reload command #1903, driver inter-instance communications via socket #1922 and others. Also convert remaining single-digit X.Y versions to X.0 double-digits. --- drivers/adelsystem_cbi.c | 2 +- drivers/al175.c | 2 +- drivers/apcsmart-old.c | 2 +- drivers/apcsmart.h | 2 +- drivers/apcupsd-ups.c | 2 +- drivers/asem.c | 2 +- drivers/bcmxcp.c | 2 +- drivers/bcmxcp_ser.c | 2 +- drivers/belkin.c | 2 +- drivers/belkinunv.c | 2 +- drivers/bestfcom.c | 2 +- drivers/bestfortress.c | 2 +- drivers/bestuferrups.c | 2 +- drivers/bestups.c | 2 +- drivers/blazer_ser.c | 2 +- drivers/blazer_usb.c | 2 +- drivers/clone-outlet.c | 2 +- drivers/clone.c | 2 +- drivers/dummy-ups.c | 2 +- drivers/etapro.c | 2 +- drivers/everups.c | 2 +- drivers/gamatronic.c | 2 +- drivers/generic_gpio_libgpiod.h | 2 +- drivers/generic_modbus.c | 2 +- drivers/genericups.c | 2 +- drivers/huawei-ups2000.c | 2 +- drivers/isbmex.c | 2 +- drivers/ivtscd.c | 2 +- drivers/liebert-esp2.c | 3 ++- drivers/liebert.c | 2 +- drivers/macosx-ups.c | 2 +- drivers/masterguard.c | 2 +- drivers/metasys.c | 2 +- drivers/mge-utalk.c | 2 +- drivers/microdowell.c | 2 +- drivers/microsol-apc.c | 2 +- drivers/netxml-ups.c | 2 +- drivers/nut-ipmipsu.c | 2 +- drivers/nutdrv_atcl_usb.c | 2 +- drivers/nutdrv_qx.c | 4 ++-- drivers/nutdrv_siemens_sitop.c | 2 +- drivers/oneac.c | 2 +- drivers/optiups.c | 2 +- drivers/phoenixcontact_modbus.c | 2 +- drivers/pijuice.c | 2 +- drivers/powercom.c | 4 ++-- drivers/powerman-pdu.c | 2 +- drivers/powerpanel.c | 2 +- drivers/rhino.c | 4 ++-- drivers/richcomm_usb.c | 2 +- drivers/riello_ser.c | 2 +- drivers/riello_usb.c | 2 +- drivers/safenet.c | 2 +- drivers/skel.c | 2 +- drivers/snmp-ups.c | 2 +- drivers/socomec_jbus.c | 2 +- drivers/solis.c | 2 +- drivers/tripplite.c | 2 +- drivers/tripplite_usb.c | 4 ++-- drivers/tripplitesu.c | 4 ++-- drivers/upscode2.c | 2 +- drivers/usbhid-ups.c | 3 ++- drivers/victronups.c | 2 +- 63 files changed, 70 insertions(+), 68 deletions(-) diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index e86a16a5c9..c64da36343 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -30,7 +30,7 @@ #include #define DRIVER_NAME "NUT ADELSYSTEM DC-UPS CB/CBI driver" -#define DRIVER_VERSION "0.01" +#define DRIVER_VERSION "0.02" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ diff --git a/drivers/al175.c b/drivers/al175.c index 70588da8b3..08b4b9b0df 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -52,7 +52,7 @@ typedef uint8_t byte_t; #define DRIVER_NAME "Eltek AL175/COMLI driver" -#define DRIVER_VERSION "0.13" +#define DRIVER_VERSION "0.14" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/apcsmart-old.c b/drivers/apcsmart-old.c index 0a2f451382..197a7b2537 100644 --- a/drivers/apcsmart-old.c +++ b/drivers/apcsmart-old.c @@ -25,7 +25,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "2.2" +#define DRIVER_VERSION "2.30" static upsdrv_info_t table_info = { "APC command table", diff --git a/drivers/apcsmart.h b/drivers/apcsmart.h index 864bc73d1c..bfd5db8794 100644 --- a/drivers/apcsmart.h +++ b/drivers/apcsmart.h @@ -24,7 +24,7 @@ #define NUT_APCSMART_H_SEEN 1 #define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "3.2" +#define DRIVER_VERSION "3.30" #define ALT_CABLE_1 "940-0095B" diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 1b4289e219..47eea55d5c 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -39,7 +39,7 @@ typedef unsigned long int nfds_t; #include "nut_stdint.h" #define DRIVER_NAME "apcupsd network client UPS driver" -#define DRIVER_VERSION "0.6" +#define DRIVER_VERSION "0.70" #define POLL_INTERVAL_MIN 10 diff --git a/drivers/asem.c b/drivers/asem.c index 04abba2f76..d35a54746a 100644 --- a/drivers/asem.c +++ b/drivers/asem.c @@ -67,7 +67,7 @@ #endif #define DRIVER_NAME "ASEM" -#define DRIVER_VERSION "0.11" +#define DRIVER_VERSION "0.12" /* Valid on ASEM PB1300 UPS */ #define BQ2060_ADDRESS 0x0B diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index 4236edc006..958cefc5dd 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -118,7 +118,7 @@ TODO List: #include "bcmxcp.h" #define DRIVER_NAME "BCMXCP UPS driver" -#define DRIVER_VERSION "0.32" +#define DRIVER_VERSION "0.33" #define MAX_NUT_NAME_LENGTH 128 #define NUT_OUTLET_POSITION 7 diff --git a/drivers/bcmxcp_ser.c b/drivers/bcmxcp_ser.c index 98e5fa9d90..6979b7f9f1 100644 --- a/drivers/bcmxcp_ser.c +++ b/drivers/bcmxcp_ser.c @@ -6,7 +6,7 @@ #include "nut_stdint.h" #define SUBDRIVER_NAME "RS-232 communication subdriver" -#define SUBDRIVER_VERSION "0.21" +#define SUBDRIVER_VERSION "0.22" /* communication driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/belkin.c b/drivers/belkin.c index 1eb21cf1fd..34a3f39b24 100644 --- a/drivers/belkin.c +++ b/drivers/belkin.c @@ -29,7 +29,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Belkin Smart protocol driver" -#define DRIVER_VERSION "0.25" +#define DRIVER_VERSION "0.26" static ssize_t init_communication(void); static ssize_t get_belkin_reply(char *buf); diff --git a/drivers/belkinunv.c b/drivers/belkinunv.c index 84881afa60..131e1247eb 100644 --- a/drivers/belkinunv.c +++ b/drivers/belkinunv.c @@ -94,7 +94,7 @@ #include "serial.h" #define DRIVER_NAME "Belkin 'Universal UPS' driver" -#define DRIVER_VERSION "0.08" +#define DRIVER_VERSION "0.09" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/bestfcom.c b/drivers/bestfcom.c index c53aa953f2..38a996dac1 100644 --- a/drivers/bestfcom.c +++ b/drivers/bestfcom.c @@ -45,7 +45,7 @@ #include "serial.h" #define DRIVER_NAME "Best Ferrups/Fortress driver" -#define DRIVER_VERSION "0.13" +#define DRIVER_VERSION "0.14" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 67fd681b12..d86d1b4daa 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -35,7 +35,7 @@ #endif #define DRIVER_NAME "Best Fortress UPS driver" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/bestuferrups.c b/drivers/bestuferrups.c index 8bed32bfc6..7ef36347cb 100644 --- a/drivers/bestuferrups.c +++ b/drivers/bestuferrups.c @@ -33,7 +33,7 @@ #include "serial.h" #define DRIVER_NAME "Best Ferrups Series ME/RE/MD driver" -#define DRIVER_VERSION "0.04" +#define DRIVER_VERSION "0.05" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/bestups.c b/drivers/bestups.c index 05a2f344f4..d388658e12 100644 --- a/drivers/bestups.c +++ b/drivers/bestups.c @@ -29,7 +29,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Best UPS driver" -#define DRIVER_VERSION "1.07" +#define DRIVER_VERSION "1.08" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/blazer_ser.c b/drivers/blazer_ser.c index 6d82bbfce7..0986ab32e2 100644 --- a/drivers/blazer_ser.c +++ b/drivers/blazer_ser.c @@ -31,7 +31,7 @@ #include "blazer.h" #define DRIVER_NAME "Megatec/Q1 protocol serial driver" -#define DRIVER_VERSION "1.58" +#define DRIVER_VERSION "1.59" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 74d0710b84..aee325b7b9 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -37,7 +37,7 @@ #endif #define DRIVER_NAME "Megatec/Q1 protocol USB driver" -#define DRIVER_VERSION "0.14" +#define DRIVER_VERSION "0.15" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/clone-outlet.c b/drivers/clone-outlet.c index 16dbbeff28..62f3cd186d 100644 --- a/drivers/clone-outlet.c +++ b/drivers/clone-outlet.c @@ -29,7 +29,7 @@ #endif #define DRIVER_NAME "clone outlet UPS Driver" -#define DRIVER_VERSION "0.02" +#define DRIVER_VERSION "0.03" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/clone.c b/drivers/clone.c index 9e9eb448f7..c12cc55d4b 100644 --- a/drivers/clone.c +++ b/drivers/clone.c @@ -31,7 +31,7 @@ #endif #define DRIVER_NAME "Clone UPS driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index c20295bd68..8a58242bce 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -47,7 +47,7 @@ #include "dummy-ups.h" #define DRIVER_NAME "Device simulation and repeater driver" -#define DRIVER_VERSION "0.15" +#define DRIVER_VERSION "0.16" /* driver description structure */ upsdrv_info_t upsdrv_info = diff --git a/drivers/etapro.c b/drivers/etapro.c index 85b88d5964..2e5fa812ef 100644 --- a/drivers/etapro.c +++ b/drivers/etapro.c @@ -55,7 +55,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "ETA PRO driver" -#define DRIVER_VERSION "0.05" +#define DRIVER_VERSION "0.06" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/everups.c b/drivers/everups.c index 63ccea879d..dc032b0fec 100644 --- a/drivers/everups.c +++ b/drivers/everups.c @@ -21,7 +21,7 @@ #include "serial.h" #define DRIVER_NAME "Ever UPS driver (serial)" -#define DRIVER_VERSION "0.04" +#define DRIVER_VERSION "0.05" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/gamatronic.c b/drivers/gamatronic.c index bf92238ffe..bf0c6ad333 100644 --- a/drivers/gamatronic.c +++ b/drivers/gamatronic.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Gamatronic UPS driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h index 43dd98dfda..193c9b8c2c 100644 --- a/drivers/generic_gpio_libgpiod.h +++ b/drivers/generic_gpio_libgpiod.h @@ -25,7 +25,7 @@ #include #define DRIVER_NAME "GPIO UPS driver" -#define DRIVER_VERSION "1.00" +#define DRIVER_VERSION "1.01" typedef struct libgpiod_data_t { struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 1b30b6e4ec..d10472b452 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -27,7 +27,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "NUT Generic Modbus driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ diff --git a/drivers/genericups.c b/drivers/genericups.c index c5d574d03b..acd2e3f6d6 100644 --- a/drivers/genericups.c +++ b/drivers/genericups.c @@ -31,7 +31,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Generic contact-closure UPS driver" -#define DRIVER_VERSION "1.38" +#define DRIVER_VERSION "1.39" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index b856fb6fb1..9ebf86ff28 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -51,7 +51,7 @@ #include "timehead.h" /* fallback gmtime_r() variants if needed (e.g. some WIN32) */ #define DRIVER_NAME "NUT Huawei UPS2000 (1kVA-3kVA) RS-232 Modbus driver" -#define DRIVER_VERSION "0.04" +#define DRIVER_VERSION "0.05" #define CHECK_BIT(var,pos) ((var) & (1<<(pos))) #define MODBUS_SLAVE_ID 1 diff --git a/drivers/isbmex.c b/drivers/isbmex.c index 6c3a7b6cef..923b46f7ee 100644 --- a/drivers/isbmex.c +++ b/drivers/isbmex.c @@ -27,7 +27,7 @@ #include #define DRIVER_NAME "ISBMEX UPS driver" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/ivtscd.c b/drivers/ivtscd.c index 4f3f0a42d2..3a07c72281 100644 --- a/drivers/ivtscd.c +++ b/drivers/ivtscd.c @@ -25,7 +25,7 @@ #include "attribute.h" #define DRIVER_NAME "IVT Solar Controller driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/liebert-esp2.c b/drivers/liebert-esp2.c index b0dbf82850..ef27cc871a 100644 --- a/drivers/liebert-esp2.c +++ b/drivers/liebert-esp2.c @@ -28,7 +28,8 @@ #define IsBitSet(val, bit) ((val) & (1 << (bit))) #define DRIVER_NAME "Liebert ESP-II serial UPS driver" -#define DRIVER_VERSION "0.05" +#define DRIVER_VERSION "0.06" + #define UPS_SHUTDOWN_DELAY 12 /* it means UPS will be shutdown 120 sec */ #define SHUTDOWN_CMD_LEN 8 diff --git a/drivers/liebert.c b/drivers/liebert.c index b07e526fc0..1c21e6e0da 100644 --- a/drivers/liebert.c +++ b/drivers/liebert.c @@ -27,7 +27,7 @@ #include "attribute.h" #define DRIVER_NAME "Liebert MultiLink UPS driver" -#define DRIVER_VERSION "1.03" +#define DRIVER_VERSION "1.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/macosx-ups.c b/drivers/macosx-ups.c index 9b4540b97a..1740320c29 100644 --- a/drivers/macosx-ups.c +++ b/drivers/macosx-ups.c @@ -29,7 +29,7 @@ #include "IOKit/ps/IOPSKeys.h" #define DRIVER_NAME "Mac OS X UPS meta-driver" -#define DRIVER_VERSION "1.3" +#define DRIVER_VERSION "1.40" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/masterguard.c b/drivers/masterguard.c index cb27f233e5..37cae77651 100644 --- a/drivers/masterguard.c +++ b/drivers/masterguard.c @@ -29,7 +29,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "MASTERGUARD UPS driver" -#define DRIVER_VERSION "0.25" +#define DRIVER_VERSION "0.26" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/metasys.c b/drivers/metasys.c index 4857c5f625..e5003b116f 100644 --- a/drivers/metasys.c +++ b/drivers/metasys.c @@ -28,7 +28,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Metasystem UPS driver" -#define DRIVER_VERSION "0.08" +#define DRIVER_VERSION "0.09" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/mge-utalk.c b/drivers/mge-utalk.c index ba8181ae29..ec27989745 100644 --- a/drivers/mge-utalk.c +++ b/drivers/mge-utalk.c @@ -69,7 +69,7 @@ /* --------------------------------------------------------------- */ #define DRIVER_NAME "MGE UPS SYSTEMS/U-Talk driver" -#define DRIVER_VERSION "0.94" +#define DRIVER_VERSION "0.95" /* driver description structure */ diff --git a/drivers/microdowell.c b/drivers/microdowell.c index 9874ead239..9b2637ea81 100644 --- a/drivers/microdowell.c +++ b/drivers/microdowell.c @@ -44,7 +44,7 @@ #define MAX_SHUTDOWN_DELAY_LEN 5 #define DRIVER_NAME "MICRODOWELL UPS driver" -#define DRIVER_VERSION "0.02" +#define DRIVER_VERSION "0.03" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/microsol-apc.c b/drivers/microsol-apc.c index 20e0cd3466..329263703f 100644 --- a/drivers/microsol-apc.c +++ b/drivers/microsol-apc.c @@ -35,7 +35,7 @@ #include "microsol-apc.h" #define DRIVER_NAME "APC Back-UPS BR series UPS driver" -#define DRIVER_VERSION "0.69" +#define DRIVER_VERSION "0.70" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index 13b0a6da5c..f58d194e98 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -42,7 +42,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "network XML UPS" -#define DRIVER_VERSION "0.44" +#define DRIVER_VERSION "0.45" /** *_OBJECT query multi-part body boundary */ #define FORM_POST_BOUNDARY "NUT-NETXML-UPS-OBJECTS" diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index dedbd8ab7e..1ed5ea72ad 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.31" +#define DRIVER_VERSION "0.32" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index f88d4c6a85..b87a3eff35 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -28,7 +28,7 @@ /* driver version */ #define DRIVER_NAME "'ATCL FOR UPS' USB driver" -#define DRIVER_VERSION "1.16" +#define DRIVER_VERSION "1.17" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 9c2919d6f9..350c555a06 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -38,8 +38,6 @@ * */ -#define DRIVER_VERSION "0.32" - #include "config.h" #include "main.h" #include "attribute.h" @@ -59,6 +57,8 @@ #define DRIVER_NAME "Generic Q* Serial driver" #endif /* QX_USB */ +#define DRIVER_VERSION "0.33" + #ifdef QX_SERIAL #include "serial.h" #define SER_WAIT_SEC 1 /* 3 seconds for Best UPS */ diff --git a/drivers/nutdrv_siemens_sitop.c b/drivers/nutdrv_siemens_sitop.c index d722213a77..ec84f4609d 100644 --- a/drivers/nutdrv_siemens_sitop.c +++ b/drivers/nutdrv_siemens_sitop.c @@ -56,7 +56,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Siemens SITOP UPS500 series driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" #define RX_BUFFER_SIZE 100 diff --git a/drivers/oneac.c b/drivers/oneac.c index 4d6dd69b34..0bb30d1f47 100644 --- a/drivers/oneac.c +++ b/drivers/oneac.c @@ -48,7 +48,7 @@ int setcmd(const char* varname, const char* setvalue); int instcmd(const char *cmdname, const char *extra); #define DRIVER_NAME "Oneac EG/ON/OZ/OB UPS driver" -#define DRIVER_VERSION "0.81" +#define DRIVER_VERSION "0.82" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/optiups.c b/drivers/optiups.c index ade3441d65..7964aab350 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -28,7 +28,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Opti-UPS driver" -#define DRIVER_VERSION "1.02" +#define DRIVER_VERSION "1.03" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/phoenixcontact_modbus.c b/drivers/phoenixcontact_modbus.c index 9bfee7d916..13aa8a0b41 100644 --- a/drivers/phoenixcontact_modbus.c +++ b/drivers/phoenixcontact_modbus.c @@ -24,7 +24,7 @@ #include #define DRIVER_NAME "NUT PhoenixContact Modbus driver" -#define DRIVER_VERSION "0.02" +#define DRIVER_VERSION "0.03" #define CHECK_BIT(var,pos) ((var) & (1<<(pos))) #define MODBUS_SLAVE_ID 192 diff --git a/drivers/pijuice.c b/drivers/pijuice.c index 1229984365..2f589bcbfa 100644 --- a/drivers/pijuice.c +++ b/drivers/pijuice.c @@ -218,7 +218,7 @@ static inline __u8* i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 l #define NOMINAL_BATTERY_VOLTAGE 4.18 #define DRIVER_NAME "PiJuice UPS driver" -#define DRIVER_VERSION "0.10" +#define DRIVER_VERSION "0.11" static uint8_t i2c_address = 0x14; static uint8_t shutdown_delay = 30; diff --git a/drivers/powercom.c b/drivers/powercom.c index 7f9819a9ec..8b22f74c84 100644 --- a/drivers/powercom.c +++ b/drivers/powercom.c @@ -85,8 +85,8 @@ #include "powercom.h" #include "math.h" -#define DRIVER_NAME "PowerCom protocol UPS driver" -#define DRIVER_VERSION "0.20" +#define DRIVER_NAME "PowerCom protocol UPS driver" +#define DRIVER_VERSION "0.21" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/powerman-pdu.c b/drivers/powerman-pdu.c index 46a432b21a..316950a47c 100644 --- a/drivers/powerman-pdu.c +++ b/drivers/powerman-pdu.c @@ -23,7 +23,7 @@ #include /* pm_err_t and other beasts */ #define DRIVER_NAME "Powerman PDU client driver" -#define DRIVER_VERSION "0.12" +#define DRIVER_VERSION "0.13" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/powerpanel.c b/drivers/powerpanel.c index 6c677b8ef9..9ec775784e 100644 --- a/drivers/powerpanel.c +++ b/drivers/powerpanel.c @@ -36,7 +36,7 @@ static subdriver_t *subdriver[] = { }; #define DRIVER_NAME "CyberPower text/binary protocol UPS driver" -#define DRIVER_VERSION "0.28" +#define DRIVER_VERSION "0.29" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/rhino.c b/drivers/rhino.c index b1eaf9e9ef..6ceab04158 100644 --- a/drivers/rhino.c +++ b/drivers/rhino.c @@ -37,8 +37,8 @@ #include "nut_stdint.h" #include "timehead.h" -#define DRIVER_NAME "Microsol Rhino UPS driver" -#define DRIVER_VERSION "0.52" +#define DRIVER_NAME "Microsol Rhino UPS driver" +#define DRIVER_VERSION "0.53" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 42dff8953c..15451a49db 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -30,7 +30,7 @@ /* driver version */ #define DRIVER_NAME "Richcomm dry-contact to USB driver" -#define DRIVER_VERSION "0.11" +#define DRIVER_VERSION "0.12" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index cd3b8a997e..f7197740a7 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -46,7 +46,7 @@ #include "riello.h" #define DRIVER_NAME "Riello serial driver" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" #define DEFAULT_OFFDELAY 5 #define DEFAULT_BOOTDELAY 5 diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index f6047129b9..451ceb07d0 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -34,7 +34,7 @@ #include "riello.h" #define DRIVER_NAME "Riello USB driver" -#define DRIVER_VERSION "0.08" +#define DRIVER_VERSION "0.09" #define DEFAULT_OFFDELAY 5 /*!< seconds (max 0xFF) */ #define DEFAULT_BOOTDELAY 5 /*!< seconds (max 0xFF) */ diff --git a/drivers/safenet.c b/drivers/safenet.c index df5da33d89..68365463fa 100644 --- a/drivers/safenet.c +++ b/drivers/safenet.c @@ -41,7 +41,7 @@ #include "safenet.h" #define DRIVER_NAME "Generic SafeNet UPS driver" -#define DRIVER_VERSION "1.7" +#define DRIVER_VERSION "1.80" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/skel.c b/drivers/skel.c index e79d5d8ea8..b5033672bb 100644 --- a/drivers/skel.c +++ b/drivers/skel.c @@ -22,7 +22,7 @@ /* #define IGNCHARS "" */ #define DRIVER_NAME "Skeleton UPS driver" -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index efb9d53f8e..a9073aaa62 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -173,7 +173,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.28" +#define DRIVER_VERSION "1.29" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/socomec_jbus.c b/drivers/socomec_jbus.c index 8eabe35844..84d585d39b 100644 --- a/drivers/socomec_jbus.c +++ b/drivers/socomec_jbus.c @@ -31,7 +31,7 @@ #include #define DRIVER_NAME "Socomec jbus driver" -#define DRIVER_VERSION "0.06" +#define DRIVER_VERSION "0.07" #define CHECK_BIT(var,pos) ((var) & (1<<(pos))) #define MODBUS_SLAVE_ID 1 diff --git a/drivers/solis.c b/drivers/solis.c index 364a21a55e..eb1cee47d0 100644 --- a/drivers/solis.c +++ b/drivers/solis.c @@ -48,7 +48,7 @@ #include "timehead.h" #define DRIVER_NAME "Microsol Solis UPS driver" -#define DRIVER_VERSION "0.68" +#define DRIVER_VERSION "0.69" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/tripplite.c b/drivers/tripplite.c index a236e5ca0d..76ec0b0a8a 100644 --- a/drivers/tripplite.c +++ b/drivers/tripplite.c @@ -117,7 +117,7 @@ #include #define DRIVER_NAME "Tripp-Lite SmartUPS driver" -#define DRIVER_VERSION "0.93" +#define DRIVER_VERSION "0.94" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 96abce57d1..84508f8f2e 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -135,8 +135,8 @@ #include #include "usb-common.h" -#define DRIVER_NAME "Tripp Lite OMNIVS / SMARTPRO driver" -#define DRIVER_VERSION "0.33" +#define DRIVER_NAME "Tripp Lite OMNIVS / SMARTPRO driver" +#define DRIVER_VERSION "0.34" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index 3a0d2c5469..a5e5d05da0 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -125,8 +125,8 @@ #include "serial.h" #include "nut_stdint.h" -#define DRIVER_NAME "Tripp Lite SmartOnline driver" -#define DRIVER_VERSION "0.06" +#define DRIVER_NAME "Tripp Lite SmartOnline driver" +#define DRIVER_VERSION "0.07" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/upscode2.c b/drivers/upscode2.c index 4bbcd976be..5dac03bf20 100644 --- a/drivers/upscode2.c +++ b/drivers/upscode2.c @@ -43,7 +43,7 @@ #include "nut_float.h" #define DRIVER_NAME "UPScode II UPS driver" -#define DRIVER_VERSION "0.90" +#define DRIVER_VERSION "0.91" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 38d9c35eea..3a8cc7120a 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -28,7 +28,8 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.49" +#define DRIVER_VERSION "0.50" + #define HU_VAR_WAITBEFORERECONNECT "waitbeforereconnect" #include "main.h" diff --git a/drivers/victronups.c b/drivers/victronups.c index f4f6ad6045..49901f43bf 100644 --- a/drivers/victronups.c +++ b/drivers/victronups.c @@ -32,7 +32,7 @@ #include "serial.h" #define DRIVER_NAME "GE/IMV/Victron UPS driver" -#define DRIVER_VERSION "0.21" +#define DRIVER_VERSION "0.22" /* driver description structure */ upsdrv_info_t upsdrv_info = { From cce80e78e0a07779788a09d7486b5c56a5c3cc86 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 15:39:32 +0200 Subject: [PATCH 0837/1232] drivers/generic_gpio_libgpiod.{c,h}, drivers/apcsmart.{c,h}: move DRIVER_NAME and DRIVER_VERSION from header to C source file as in other drivers --- drivers/apcsmart.c | 3 +++ drivers/apcsmart.h | 3 --- drivers/generic_gpio_libgpiod.c | 3 +++ drivers/generic_gpio_libgpiod.h | 8 +++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 261b18f5f7..de137f8e09 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -35,6 +35,9 @@ #include "apcsmart.h" #include "apcsmart_tabs.h" +#define DRIVER_NAME "APC Smart protocol driver" +#define DRIVER_VERSION "3.30" + #ifdef WIN32 # ifndef ECANCELED # define ECANCELED ERROR_CANCELLED diff --git a/drivers/apcsmart.h b/drivers/apcsmart.h index bfd5db8794..5a60f83eb5 100644 --- a/drivers/apcsmart.h +++ b/drivers/apcsmart.h @@ -23,9 +23,6 @@ #ifndef NUT_APCSMART_H_SEEN #define NUT_APCSMART_H_SEEN 1 -#define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "3.30" - #define ALT_CABLE_1 "940-0095B" /* diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 99116bbe0e..dded983b85 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -26,6 +26,9 @@ #include "generic_gpio_common.h" #include "generic_gpio_libgpiod.h" +#define DRIVER_NAME "GPIO UPS driver" +#define DRIVER_VERSION "1.01" + /* driver description structure */ upsdrv_info_t upsdrv_info = { DRIVER_NAME, diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h index 193c9b8c2c..a1e7b55977 100644 --- a/drivers/generic_gpio_libgpiod.h +++ b/drivers/generic_gpio_libgpiod.h @@ -1,5 +1,3 @@ -#ifndef GENERIC_GPIO_LIBGPIOD_H -#define GENERIC_GPIO_LIBGPIOD_H /* generic_gpio_libgpiod.h - gpiod based NUT driver definitions for GPIO attached UPS devices * * Copyright (C) @@ -22,10 +20,10 @@ * */ -#include +#ifndef GENERIC_GPIO_LIBGPIOD_H +#define GENERIC_GPIO_LIBGPIOD_H -#define DRIVER_NAME "GPIO UPS driver" -#define DRIVER_VERSION "1.01" +#include typedef struct libgpiod_data_t { struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ From 62a3638b3f8df08c27e76d73a8e4c0d00a8093ee Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 15:43:39 +0200 Subject: [PATCH 0838/1232] drivers/generic_gpio*.h: style (whitespace) fixes --- drivers/generic_gpio_common.h | 61 +++++++++++++++++---------------- drivers/generic_gpio_libgpiod.h | 12 +++---- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/drivers/generic_gpio_common.h b/drivers/generic_gpio_common.h index 65c60a9e34..3b17a86c9a 100644 --- a/drivers/generic_gpio_common.h +++ b/drivers/generic_gpio_common.h @@ -1,5 +1,3 @@ -#ifndef GENERIC_GPIO_COMMON_H -#define GENERIC_GPIO_COMMON_H /* generic_gpio_common.h - common NUT driver definitions for GPIO attached UPS devices * * Copyright (C) @@ -22,47 +20,50 @@ * */ +#ifndef GENERIC_GPIO_COMMON_H_SEEN +#define GENERIC_GPIO_COMMON_H_SEEN + #include #include #include /* rules commands definition */ -#define RULES_CMD_NOT -2 -#define RULES_CMD_AND -3 -#define RULES_CMD_OR -4 -#define RULES_CMD_OBR -5 -#define RULES_CMD_CBR -6 -#define RULES_CMD_LAST RULES_CMD_CBR +#define RULES_CMD_NOT -2 +#define RULES_CMD_AND -3 +#define RULES_CMD_OR -4 +#define RULES_CMD_OBR -5 +#define RULES_CMD_CBR -6 +#define RULES_CMD_LAST RULES_CMD_CBR /* run option definitions */ -#define ROPT_REQRES 0x00000001 /* reserve GPIO lines only during request processing */ -#define ROPT_EVMODE 0x00000002 /* event driven run */ +#define ROPT_REQRES 0x00000001 /* reserve GPIO lines only during request processing */ +#define ROPT_EVMODE 0x00000002 /* event driven run */ /* buffer size for chipName arrays */ #define NUT_GPIO_CHIPNAMEBUF 32 -#define NUT_GPIO_SUBTYPEBUF 16 +#define NUT_GPIO_SUBTYPEBUF 16 typedef struct rulesint_t { /* structure to store processed rules configuration per each state */ - char stateName[12]; /* NUT state name for rules in cRules */ - int archVal; /* previous state value */ - int currVal; /* current state value */ - int subCount; /* element count in translated rules subitem */ - int cRules[]; /* translated rules subitem - rules commands followed by line number(s) */ -} rulesint; + char stateName[12]; /* NUT state name for rules in cRules */ + int archVal; /* previous state value */ + int currVal; /* current state value */ + int subCount; /* element count in translated rules subitem */ + int cRules[]; /* translated rules subitem - rules commands followed by line number(s) */ +} rulesint; typedef struct gpioups_t { - void *lib_data; /* pointer to driver's gpio support library data structure */ - const char *chipName; /* port or file name to reference GPIO chip */ - int initial; /* initialization flag - 0 on 1st entry */ - int runOptions; /* run options, not yet used */ - int aInfoAvailable; /* non-zero if previous state information is available */ - int chipLinesCount; /* gpio chip lines count, set after sucessful open */ - int upsLinesCount; /* no of lines used in rules */ - int *upsLines; /* lines numbers */ - int *upsLinesStates; /* lines states */ - int upsMaxLine; /* maximum line number referenced in rules */ - int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ - struct rulesint_t **rules; + void *lib_data; /* pointer to driver's gpio support library data structure */ + const char *chipName; /* port or file name to reference GPIO chip */ + int initial; /* initialization flag - 0 on 1st entry */ + int runOptions; /* run options, not yet used */ + int aInfoAvailable; /* non-zero if previous state information is available */ + int chipLinesCount; /* gpio chip lines count, set after sucessful open */ + int upsLinesCount; /* no of lines used in rules */ + int *upsLines; /* lines numbers */ + int *upsLinesStates; /* lines states */ + int upsMaxLine; /* maximum line number referenced in rules */ + int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ + struct rulesint_t **rules; } gpioups; extern struct gpioups_t *gpioupsfd; @@ -82,4 +83,4 @@ int calc_rule_states(int upsLinesStates[], int cRules[], int subCount, int sInde void update_ups_states(struct gpioups_t *gpioupsfd); # endif /* DRIVERS_MAIN_WITHOUT_MAIN */ -#endif /* GENERIC_GPIO_COMMON_H */ +#endif /* GENERIC_GPIO_COMMON_H_SEEN */ diff --git a/drivers/generic_gpio_libgpiod.h b/drivers/generic_gpio_libgpiod.h index a1e7b55977..66f13b4511 100644 --- a/drivers/generic_gpio_libgpiod.h +++ b/drivers/generic_gpio_libgpiod.h @@ -20,15 +20,15 @@ * */ -#ifndef GENERIC_GPIO_LIBGPIOD_H -#define GENERIC_GPIO_LIBGPIOD_H +#ifndef GENERIC_GPIO_LIBGPIOD_H_SEEN +#define GENERIC_GPIO_LIBGPIOD_H_SEEN #include typedef struct libgpiod_data_t { - struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ - struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ - struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ + struct gpiod_chip *gpioChipHandle; /* libgpiod chip handle when opened */ + struct gpiod_line_bulk gpioLines; /* libgpiod lines to monitor */ + struct gpiod_line_bulk gpioEventLines; /* libgpiod lines for event monitoring */ } libgpiod_data; -#endif /* GENERIC_GPIO_LIBGPIOD_H */ +#endif /* GENERIC_GPIO_LIBGPIOD_H_SEEN */ From 0bea0af6a4d59ef657b8703d61635415ebffdddd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 22:06:04 +0200 Subject: [PATCH 0839/1232] Wholesale update of website URL to "https://www.networkupstools.org" --- AUTHORS | 2 +- NEWS | 4 ++-- README | 2 +- data/html/header.html.in | 2 +- data/html/index.html | 2 +- docs/FAQ.txt | 6 ++--- docs/asciidoc.conf | 2 +- docs/documentation.txt | 2 +- docs/download.txt | 22 +++++++++--------- docs/features.txt | 2 +- docs/hid-subdrivers.txt | 2 +- docs/history.txt | 2 +- docs/man/adelsystem_cbi.txt | 2 +- docs/man/al175.txt | 2 +- docs/man/apcsmart-old.txt | 4 ++-- docs/man/apcsmart.txt | 4 ++-- docs/man/apcupsd-ups.txt | 2 +- docs/man/asem.txt | 2 +- docs/man/bcmxcp.txt | 2 +- docs/man/bcmxcp_usb.txt | 2 +- docs/man/belkin.txt | 2 +- docs/man/belkinunv.txt | 4 ++-- docs/man/bestfcom.txt | 2 +- docs/man/bestfortress.txt | 2 +- docs/man/bestuferrups.txt | 2 +- docs/man/bestups.txt | 2 +- docs/man/blazer-common.txt | 4 ++-- docs/man/clone.txt | 2 +- docs/man/dummy-ups.txt | 4 ++-- docs/man/etapro.txt | 2 +- docs/man/everups.txt | 2 +- docs/man/gamatronic.txt | 2 +- docs/man/generic_gpio.txt | 2 +- docs/man/generic_modbus.txt | 2 +- docs/man/genericups.txt | 2 +- docs/man/hosts.conf.txt | 2 +- docs/man/huawei-ups2000.txt | 2 +- docs/man/isbmex.txt | 2 +- docs/man/ivtscd.txt | 2 +- docs/man/libupsclient-config.txt | 2 +- docs/man/liebert-esp2.txt | 2 +- docs/man/liebert.txt | 2 +- docs/man/macosx-ups.txt | 2 +- docs/man/masterguard.txt | 2 +- docs/man/metasys.txt | 2 +- docs/man/mge-shut.txt | 2 +- docs/man/mge-utalk.txt | 2 +- docs/man/microdowell.txt | 2 +- docs/man/microsol-apc.txt | 2 +- docs/man/netxml-ups.txt | 2 +- docs/man/nut-driver-enumerator.txt | 2 +- docs/man/nut-ipmipsu.txt | 2 +- docs/man/nut-recorder.txt | 2 +- docs/man/nut-scanner.txt | 2 +- docs/man/nut.conf.txt | 2 +- docs/man/nutdrv_atcl_usb.txt | 2 +- docs/man/nutdrv_qx.txt | 6 ++--- docs/man/nutdrv_siemens_sitop.txt | 2 +- docs/man/nutupsdrv.txt | 2 +- docs/man/oneac.txt | 2 +- docs/man/optiups.txt | 2 +- docs/man/phoenixcontact_modbus.txt | 2 +- docs/man/pijuice.txt | 2 +- docs/man/powercom.txt | 2 +- docs/man/powerman-pdu.txt | 2 +- docs/man/powerpanel.txt | 2 +- docs/man/rhino.txt | 2 +- docs/man/richcomm_usb.txt | 2 +- docs/man/riello_ser.txt | 2 +- docs/man/riello_usb.txt | 2 +- docs/man/safenet.txt | 2 +- docs/man/skel.txt | 2 +- docs/man/snmp-ups.txt | 4 ++-- docs/man/sockdebug.txt | 2 +- docs/man/socomec_jbus.txt | 2 +- docs/man/solis.txt | 2 +- docs/man/tripplite.txt | 2 +- docs/man/tripplite_usb.txt | 2 +- docs/man/tripplitesu.txt | 2 +- docs/man/ups.conf.txt | 2 +- docs/man/upsc.txt | 2 +- docs/man/upscmd.txt | 2 +- docs/man/upscode2.txt | 2 +- docs/man/upsd.conf.txt | 2 +- docs/man/upsd.txt | 2 +- docs/man/upsd.users.txt | 2 +- docs/man/upsdrvctl.txt | 2 +- docs/man/upsdrvsvcctl.txt | 2 +- docs/man/upsimage.cgi.txt | 2 +- docs/man/upslog.txt | 2 +- docs/man/upsmon.conf.txt | 2 +- docs/man/upsmon.txt | 2 +- docs/man/upsrw.txt | 2 +- docs/man/upssched.conf.txt | 2 +- docs/man/upssched.txt | 2 +- docs/man/upsset.cgi.txt | 2 +- docs/man/upsset.conf.txt | 2 +- docs/man/upsstats.cgi.txt | 2 +- docs/man/upsstats.html.txt | 2 +- docs/man/usbhid-ups.txt | 2 +- docs/man/victronups.txt | 2 +- docs/new-clients.txt | 2 +- docs/nut-names.txt | 2 +- docs/security.txt | 8 +++---- docs/snmp.txt | 2 +- docs/support.txt | 2 +- docs/user-manual.txt | 2 +- drivers/apcsmart.c | 2 +- drivers/blazer.c | 2 +- drivers/blazer.h | 2 +- drivers/blazer_ser.c | 2 +- drivers/blazer_usb.c | 2 +- drivers/delta_ups-mib.c | 2 +- drivers/eaton-pdu-marlin-mib.c | 2 +- drivers/hpe-pdu-mib.c | 2 +- drivers/libhid.c | 2 +- drivers/libusb0.c | 2 +- drivers/libusb1.c | 2 +- drivers/nut_libusb.h | 2 +- drivers/optiups.c | 2 +- drivers/riello.c | 4 ++-- drivers/riello.h | 4 ++-- drivers/riello_ser.c | 4 ++-- drivers/riello_usb.c | 2 +- indent.sh | 2 +- scripts/Aix/nut-aix.spec.in | 4 ++-- scripts/Solaris/pkginfo.in | 2 +- scripts/Windows/build-mingw-nut.sh | 2 +- scripts/perl/Nut.pm | 2 +- scripts/python/app/locale/NUT-Monitor.pot | 2 +- .../app/locale/fr/LC_MESSAGES/NUT-Monitor.mo | Bin 6503 -> 6505 bytes scripts/python/app/locale/fr/fr.po | 4 ++-- .../app/locale/it/LC_MESSAGES/NUT-Monitor.mo | Bin 6462 -> 6464 bytes scripts/python/app/locale/it/it.po | 4 ++-- .../app/locale/ru/LC_MESSAGES/NUT-Monitor.mo | Bin 9168 -> 9170 bytes scripts/python/app/locale/ru/ru.po | 4 ++-- scripts/python/app/ui/aboutdialog1.ui | 2 +- scripts/python/app/ui/gui-1.3.glade | 2 +- scripts/python/app/ui/gui-1.3.glade.h | 2 +- server/netget.c | 2 +- server/netmisc.c | 2 +- tools/nut-ddl-dump.sh | 2 +- tools/nut-usbinfo.pl | 2 +- 143 files changed, 171 insertions(+), 171 deletions(-) diff --git a/AUTHORS b/AUTHORS index 5a96fa7db3..4c9619133a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -54,7 +54,7 @@ D: Provided a Best Fortress for development of a Best driver (bestups) N: Russell Kroll E: rkroll@exploits.org -W: http://www.networkupstools.org/ +W: https://www.networkupstools.org/ D: Original NUT author and coordinator P: 1024D/9DC0E77E 6A5C 7D2D 7945 C022 6104 D421 D61D C97F 9DC0 E77E diff --git a/NEWS b/NEWS index 5aa7bbb2e4..11385cf61d 100644 --- a/NEWS +++ b/NEWS @@ -1091,7 +1091,7 @@ Release notes for NUT 2.6.5 - what's new since 2.6.4: not executed (report and patch from Oliver Schonefeld) - Website hosting: free NUT from Eaton website hosting - NUT website (http://www.networkupstools.org) is no longer hosted by Eaton. + NUT website (https://www.networkupstools.org) is no longer hosted by Eaton. Arnaud Quette (NUT project leader) has taken over NUT hosting on his own, to give NUT back some independence. This effort is also part of a logic to stop crediting Eaton for @@ -1236,7 +1236,7 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3: - Provide an Uncomplicated Firewall (UFW) profile (nut.ufw.profile) - Riello protocols have been officially published in NUT protocols library: - http://www.networkupstools.org/ups-protocols.html#_riello + https://www.networkupstools.org/ups-protocols.html#_riello - Duplicate instances of upsd / upsmon are now detected upon startup diff --git a/README b/README index 608c52c1b2..85ef108867 100644 --- a/README +++ b/README @@ -171,7 +171,7 @@ For example, it is available on Debian systems as: /usr/share/nut/driver.list -This table is also available link:http://www.networkupstools.org/stable-hcl.html[online]. +This table is also available link:https://www.networkupstools.org/stable-hcl.html[online]. If your driver has vanished, see the link:FAQ.html[FAQ] and diff --git a/data/html/header.html.in b/data/html/header.html.in index 6e222a5b1e..53e4778226 100644 --- a/data/html/header.html.in +++ b/data/html/header.html.in @@ -13,7 +13,7 @@ Network UPS Tools - +
diff --git a/data/html/index.html b/data/html/index.html index 953cc376ce..15cff115d2 100644 --- a/data/html/index.html +++ b/data/html/index.html @@ -2,7 +2,7 @@ -Network UPS Tools -- http://www.networkupstools.org +Network UPS Tools -- https://www.networkupstools.org diff --git a/docs/FAQ.txt b/docs/FAQ.txt index 805e175f9b..a04d1d29f2 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -141,7 +141,7 @@ wandered off, one can be built rather easily with some connectors and cable -- there's no fancy wiring or resistors. See this URL for a handy diagram: -http://www.networkupstools.org/cables/940-0024C.jpg +https://www.networkupstools.org/cables/940-0024C.jpg There is also a text version of that diagram in the docs/cables directory of the NUT source distribution. Either one should allow @@ -581,7 +581,7 @@ There are several driver to support USB models. Refer to the 'driver-name' (8) man page for more information. You can also consult the Hardware Compatibility List (HCL) and filter on USB: -http://www.networkupstools.org/stable-hcl.html?connection=USB +https://www.networkupstools.org/stable-hcl.html?connection=USB == My USB UPS has a bogus Vendor ID 0x0001 and Product ID 0x0000, what driver supports it? @@ -736,7 +736,7 @@ Or a variation like... == I can't run this because there's no package for it. Why isn't this in a package yet? Sorry, can't help you there. All official releases are source code -and are posted on http://www.networkupstools.org/ along with PGP +and are posted on https://www.networkupstools.org/ along with PGP signatures for verification. This means all packages have been built by a third party. If you diff --git a/docs/asciidoc.conf b/docs/asciidoc.conf index fedf952a37..10a6487efa 100644 --- a/docs/asciidoc.conf +++ b/docs/asciidoc.conf @@ -48,7 +48,7 @@ endif::chunked_format[] # FIXME: linkdoc does not support 'anchor' ifdef::pdf_format[] [linkman-inlinemacro] -{target}{0?({0})} +{target}{0?({0})} [linkdoc-inlinemacro] {1} endif::pdf_format[] diff --git a/docs/documentation.txt b/docs/documentation.txt index 101218eb15..6f5b8035d0 100644 --- a/docs/documentation.txt +++ b/docs/documentation.txt @@ -43,7 +43,7 @@ ifndef::website[] - link:ups-protocols.html[UPS protocols library] - link:../man/index.html#Developer_man[Developer manual pages] - link:nut-qa.html[NUT Quality Assurance] -- link:http://www.networkupstools.org/ddl/index.html[Devices Dumps Library (DDL)]: Provides simulation data to the linkman:dummy-ups[8] driver +- link:https://www.networkupstools.org/ddl/index.html[Devices Dumps Library (DDL)]: Provides simulation data to the linkman:dummy-ups[8] driver endif::website[] Data dumps for the DDL diff --git a/docs/download.txt b/docs/download.txt index 302426e78d..b0de6e9c07 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -23,14 +23,14 @@ to do so. Stable tree: {tree_version} ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- link:http://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz[nut-{revision}.tar.gz] -- link:http://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.sig[PGP/GPG signature] -- link:http://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.sha256[SHA-256 sum] -- link:http://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.md5[MD5 sum] -- link:http://www.networkupstools.org/source/{tree_version}/new-{revision}.txt[Release notes] -- link:http://www.networkupstools.org/source/{tree_version}/ChangeLog[ChangeLog] +- link:https://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz[nut-{revision}.tar.gz] +- link:https://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.sig[PGP/GPG signature] +- link:https://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.sha256[SHA-256 sum] +- link:https://www.networkupstools.org/source/{tree_version}/nut-{revision}.tar.gz.md5[MD5 sum] +- link:https://www.networkupstools.org/source/{tree_version}/new-{revision}.txt[Release notes] +- link:https://www.networkupstools.org/source/{tree_version}/ChangeLog[ChangeLog] -You can also browse the link:http://www.networkupstools.org/source/{tree_version}/[stable source directory]. +You can also browse the link:https://www.networkupstools.org/source/{tree_version}/[stable source directory]. Development tree: ~~~~~~~~~~~~~~~~~ @@ -107,7 +107,7 @@ latest *[tarball]* link towards the top of the page, and be sure to check the Older versions ~~~~~~~~~~~~~~ -link:http://www.networkupstools.org/source/[Browse source directory] +link:https://www.networkupstools.org/source/[Browse source directory] Binary packages @@ -165,7 +165,7 @@ link:https://github.com/networkupstools/nut/wiki/Links-to-distribution-packaging - Windows (complete port, Beta): - * link:http://www.networkupstools.org/package/windows/NUT-Installer-2.6.5-6.msi[Windows MSI installer 2.6.5-6] + * link:https://www.networkupstools.org/package/windows/NUT-Installer-2.6.5-6.msi[Windows MSI installer 2.6.5-6] Java packages @@ -175,10 +175,10 @@ Java packages link:https://github.com/networkupstools/jNut[GitHub repository]. - NUT Java support (client side, Beta) - link:http://www.networkupstools.org/package/java/jNut-0.2-SNAPSHOT.tar.gz[jNUT 0.2-SNAPSHOT] + link:https://www.networkupstools.org/package/java/jNut-0.2-SNAPSHOT.tar.gz[jNUT 0.2-SNAPSHOT] - NUT Java Web support (client side using REST, Beta) - link:http://www.networkupstools.org/package/java/jNutWebAPI-0.2-SNAPSHOT-src.tar.gz[jNutWebAPI 0.2-SNAPSHOT (sources)] + link:https://www.networkupstools.org/package/java/jNutWebAPI-0.2-SNAPSHOT-src.tar.gz[jNutWebAPI 0.2-SNAPSHOT (sources)] Virtualization packages ----------------------- diff --git a/docs/features.txt b/docs/features.txt index 631bdbcac5..65dd6d85e8 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -5,7 +5,7 @@ NUT provides many features, and is always improving. Thus this list may lag behind the current code. Features frequently appear during the development cycles, so be sure to look at -the link:http://www.networkupstools.org/download.html[release notes and change logs] +the link:https://www.networkupstools.org/download.html[release notes and change logs] to see the latest additions. //////////////////////////////////////////////////////////////////////////////// diff --git a/docs/hid-subdrivers.txt b/docs/hid-subdrivers.txt index 731fdcfa38..253bb2cab3 100644 --- a/docs/hid-subdrivers.txt +++ b/docs/hid-subdrivers.txt @@ -324,7 +324,7 @@ Typical troubleshooting of suspected firmware/protocol issues goes like this: the first step above, and run it through HIDRDD * Look at the HIDRDD output, with reference to any documents related to your device and the USB/HID power devices class available in NUT documentation, - e.g. at https://networkupstools.org/ups-protocols.html + e.g. at https://www.networkupstools.org/ups-protocols.html * Especially look for inconsistencies in the USB HID report descriptors (RD): * between the min/max (logical and physical) values, * the sizes of the report fields they apply to, diff --git a/docs/history.txt b/docs/history.txt index 4db0a359e3..633e6b2c71 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -350,7 +350,7 @@ attached to exploits.org is not going to work. The solution was to register a new domain and set up mirrors. There are two initial web servers, with more on the way. The main project URL has changed -from `http://www.exploits.org/nut/` to http://www.networkupstools.org. +from `http://www.exploits.org/nut/` to https://www.networkupstools.org. The actual content is hosted on various mirrors which are updated regularly with rsync, so the days of dribbling bits through my DSL should be over. diff --git a/docs/man/adelsystem_cbi.txt b/docs/man/adelsystem_cbi.txt index e8d1bd9e03..5cbe3d45c1 100644 --- a/docs/man/adelsystem_cbi.txt +++ b/docs/man/adelsystem_cbi.txt @@ -107,5 +107,5 @@ linkman:nutupsdrv[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * libmodbus home page: http://libmodbus.org diff --git a/docs/man/al175.txt b/docs/man/al175.txt index 7ba616b730..c6a9b1da6d 100644 --- a/docs/man/al175.txt +++ b/docs/man/al175.txt @@ -80,4 +80,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/apcsmart-old.txt b/docs/man/apcsmart-old.txt index 6ca4cffe35..200dffe351 100644 --- a/docs/man/apcsmart-old.txt +++ b/docs/man/apcsmart-old.txt @@ -40,7 +40,7 @@ definition described below. If your 940-0024C cable is broken or missing, use this diagram to build a clone: -http://www.networkupstools.org/cables/940-0024C.jpg +https://www.networkupstools.org/cables/940-0024C.jpg EXTRA ARGUMENTS --------------- @@ -106,4 +106,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/apcsmart.txt b/docs/man/apcsmart.txt index 9a314519e0..09ba08e011 100644 --- a/docs/man/apcsmart.txt +++ b/docs/man/apcsmart.txt @@ -94,7 +94,7 @@ definition described below. If your 940-xx24X cable is broken or missing, use this diagram to build a clone: -http://www.networkupstools.org/cables.html#_940_0024c_clone +https://www.networkupstools.org/cables.html#_940_0024c_clone NOTE: The "xx" is either "00" for a short cable, or the number of feet of a longer cable. The "X" is a letter representing the minor revision @@ -409,6 +409,6 @@ linkman:solis[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ // vim: tw=80 ai si ts=8 sts=4 sw=4 et : diff --git a/docs/man/apcupsd-ups.txt b/docs/man/apcupsd-ups.txt index 74f2b164c5..83af59d8ac 100644 --- a/docs/man/apcupsd-ups.txt +++ b/docs/man/apcupsd-ups.txt @@ -111,5 +111,5 @@ linkman:nutupsdrv[8] Internet Resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * The apcupsd home page: http://www.apcupsd.org/ diff --git a/docs/man/asem.txt b/docs/man/asem.txt index 838ddafc70..277a3279de 100644 --- a/docs/man/asem.txt +++ b/docs/man/asem.txt @@ -87,4 +87,4 @@ Internet resources: * PB1300 specifications: http://www.asem.it/en/products/industrial-automation/box-pcs/performance/pb1300/ * BQ2060 datasheet: http://www.ti.com/lit/ds/symlink/bq2060.pdf -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/bcmxcp.txt b/docs/man/bcmxcp.txt index 303d404132..b9ca0e61d2 100644 --- a/docs/man/bcmxcp.txt +++ b/docs/man/bcmxcp.txt @@ -97,4 +97,4 @@ linkman:bcmxcp_usb[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/bcmxcp_usb.txt b/docs/man/bcmxcp_usb.txt index 4906be1c30..5151a1885d 100644 --- a/docs/man/bcmxcp_usb.txt +++ b/docs/man/bcmxcp_usb.txt @@ -133,4 +133,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/belkin.txt b/docs/man/belkin.txt index 57e032042d..5db6d91560 100644 --- a/docs/man/belkin.txt +++ b/docs/man/belkin.txt @@ -61,4 +61,4 @@ linkman:usbhid-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/belkinunv.txt b/docs/man/belkinunv.txt index 0bbbb7710c..dd6424e894 100644 --- a/docs/man/belkinunv.txt +++ b/docs/man/belkinunv.txt @@ -356,8 +356,8 @@ linkman:usbhid-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * The documentation for the protocol used by this UPS: link:http://www.mscs.dal.ca/~selinger/ups/belkin-universal-ups.html[belkin-universal-ups.html] - (link:https://networkupstools.org/protocols/belkin-universal.html[replica + (link:https://www.networkupstools.org/protocols/belkin-universal.html[replica on NUT site]) diff --git a/docs/man/bestfcom.txt b/docs/man/bestfcom.txt index cc40c2be31..7309cebb29 100644 --- a/docs/man/bestfcom.txt +++ b/docs/man/bestfcom.txt @@ -45,4 +45,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/bestfortress.txt b/docs/man/bestfortress.txt index d2b7ef6f4b..5593619cf7 100644 --- a/docs/man/bestfortress.txt +++ b/docs/man/bestfortress.txt @@ -55,4 +55,4 @@ linkman:bestups[8], linkman:bestuferrups[8], linkman:bestfcom[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/bestuferrups.txt b/docs/man/bestuferrups.txt index cfe857db89..33059090ac 100644 --- a/docs/man/bestuferrups.txt +++ b/docs/man/bestuferrups.txt @@ -42,4 +42,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/bestups.txt b/docs/man/bestups.txt index d4287e573c..6c4561c9a1 100644 --- a/docs/man/bestups.txt +++ b/docs/man/bestups.txt @@ -133,4 +133,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/blazer-common.txt b/docs/man/blazer-common.txt index 7124cccdaa..d9d6f99096 100644 --- a/docs/man/blazer-common.txt +++ b/docs/man/blazer-common.txt @@ -311,5 +311,5 @@ linkman:nutupsdrv[8], linkman:upsc[8], linkman:upscmd[8], linkman:upsrw[8] Internet Resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ -* The NUT HCL: http://www.networkupstools.org/stable-hcl.html +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ +* The NUT HCL: https://www.networkupstools.org/stable-hcl.html diff --git a/docs/man/clone.txt b/docs/man/clone.txt index 555e5c7478..b4bb54e5e7 100644 --- a/docs/man/clone.txt +++ b/docs/man/clone.txt @@ -142,4 +142,4 @@ linkman:dummy-ups[8] Internet Resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/dummy-ups.txt b/docs/man/dummy-ups.txt index e3ed2f656a..8ef2f555fa 100644 --- a/docs/man/dummy-ups.txt +++ b/docs/man/dummy-ups.txt @@ -128,7 +128,7 @@ linkman:upsc[8] dump (`: `). So you can easily create definition files from an existing UPS using `upsc > file.dev`. Note that the Network UPS project provides an extensive -link:https://networkupstools.org/ddl/index.html[DDL (Devices Dumps Library)] +link:https://www.networkupstools.org/ddl/index.html[DDL (Devices Dumps Library)] with files which can be used for modelling real devices. Entries for the DDL library are best prepared with the link:https://raw.githubusercontent.com/networkupstools/nut/master/tools/nut-ddl-dump.sh[`tools/nut-ddl-dump.sh`] @@ -282,4 +282,4 @@ linkman:clone[8] Internet Resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/etapro.txt b/docs/man/etapro.txt index 86d921286a..f5eeca0cbb 100644 --- a/docs/man/etapro.txt +++ b/docs/man/etapro.txt @@ -40,4 +40,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/everups.txt b/docs/man/everups.txt index 7700982051..564d823587 100644 --- a/docs/man/everups.txt +++ b/docs/man/everups.txt @@ -47,4 +47,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/gamatronic.txt b/docs/man/gamatronic.txt index 95122954ba..dcf1aafb63 100644 --- a/docs/man/gamatronic.txt +++ b/docs/man/gamatronic.txt @@ -41,4 +41,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/generic_gpio.txt b/docs/man/generic_gpio.txt index 4899378706..5e859254f4 100644 --- a/docs/man/generic_gpio.txt +++ b/docs/man/generic_gpio.txt @@ -123,5 +123,5 @@ linkman:nutupsdrv[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * libgpiod home page: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/ diff --git a/docs/man/generic_modbus.txt b/docs/man/generic_modbus.txt index 6041a76c8d..627474f45c 100644 --- a/docs/man/generic_modbus.txt +++ b/docs/man/generic_modbus.txt @@ -245,5 +245,5 @@ linkman:nutupsdrv[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * libmodbus home page: http://libmodbus.org diff --git a/docs/man/genericups.txt b/docs/man/genericups.txt index 54c4a6b01d..a67eb68289 100644 --- a/docs/man/genericups.txt +++ b/docs/man/genericups.txt @@ -404,4 +404,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/hosts.conf.txt b/docs/man/hosts.conf.txt index 8d86ea8789..1bf23da3c2 100644 --- a/docs/man/hosts.conf.txt +++ b/docs/man/hosts.conf.txt @@ -37,4 +37,4 @@ linkman:upsset.cgi[8], linkman:upsstats.cgi[8], linkman:upsimage.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/huawei-ups2000.txt b/docs/man/huawei-ups2000.txt index 51418d9634..f2c0f676c0 100644 --- a/docs/man/huawei-ups2000.txt +++ b/docs/man/huawei-ups2000.txt @@ -395,7 +395,7 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * Huawei UPS2000-A (1 kVA-3 kVA) User Manual: https://support.huawei.com/enterprise/en/doc/EDOC1000084260 * Huawei UPS2000 (1 kVA-3 kVA) Modbus Protocol Development Guide: diff --git a/docs/man/isbmex.txt b/docs/man/isbmex.txt index 985f0ff429..ba7c76b8a1 100644 --- a/docs/man/isbmex.txt +++ b/docs/man/isbmex.txt @@ -40,4 +40,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/ivtscd.txt b/docs/man/ivtscd.txt index 0696c87847..c45aafd4a4 100644 --- a/docs/man/ivtscd.txt +++ b/docs/man/ivtscd.txt @@ -39,4 +39,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/libupsclient-config.txt b/docs/man/libupsclient-config.txt index 526276c301..1e496c7645 100644 --- a/docs/man/libupsclient-config.txt +++ b/docs/man/libupsclient-config.txt @@ -46,4 +46,4 @@ linkman:upsclient[3] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/liebert-esp2.txt b/docs/man/liebert-esp2.txt index 876f3a5ecd..fb6509a862 100644 --- a/docs/man/liebert-esp2.txt +++ b/docs/man/liebert-esp2.txt @@ -66,4 +66,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/liebert.txt b/docs/man/liebert.txt index b91365989b..5798851839 100644 --- a/docs/man/liebert.txt +++ b/docs/man/liebert.txt @@ -50,4 +50,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/macosx-ups.txt b/docs/man/macosx-ups.txt index c7140caec3..16752ca271 100644 --- a/docs/man/macosx-ups.txt +++ b/docs/man/macosx-ups.txt @@ -82,5 +82,5 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * The apcupsd home page: http://www.apcupsd.org/ diff --git a/docs/man/masterguard.txt b/docs/man/masterguard.txt index 373fc2f450..69ff47c67c 100644 --- a/docs/man/masterguard.txt +++ b/docs/man/masterguard.txt @@ -58,4 +58,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/metasys.txt b/docs/man/metasys.txt index d134fe5fc8..68d3f6dbe6 100644 --- a/docs/man/metasys.txt +++ b/docs/man/metasys.txt @@ -66,4 +66,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/mge-shut.txt b/docs/man/mge-shut.txt index 91d96b7fa8..d558613f2e 100644 --- a/docs/man/mge-shut.txt +++ b/docs/man/mge-shut.txt @@ -96,4 +96,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/mge-utalk.txt b/docs/man/mge-utalk.txt index 4dd0384b02..b287f56ba2 100644 --- a/docs/man/mge-utalk.txt +++ b/docs/man/mge-utalk.txt @@ -97,4 +97,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/microdowell.txt b/docs/man/microdowell.txt index a23ead2aff..820a86695c 100644 --- a/docs/man/microdowell.txt +++ b/docs/man/microdowell.txt @@ -41,4 +41,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/microsol-apc.txt b/docs/man/microsol-apc.txt index 74e3225445..015f9866db 100644 --- a/docs/man/microsol-apc.txt +++ b/docs/man/microsol-apc.txt @@ -70,4 +70,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/netxml-ups.txt b/docs/man/netxml-ups.txt index acc672ee08..84e8d4f222 100644 --- a/docs/man/netxml-ups.txt +++ b/docs/man/netxml-ups.txt @@ -122,4 +122,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nut-driver-enumerator.txt b/docs/man/nut-driver-enumerator.txt index 6fe92dbafa..5b177d5a37 100644 --- a/docs/man/nut-driver-enumerator.txt +++ b/docs/man/nut-driver-enumerator.txt @@ -147,4 +147,4 @@ linkman:upsdrvsvcctl[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nut-ipmipsu.txt b/docs/man/nut-ipmipsu.txt index fc6a5e4761..8cda9c28ea 100644 --- a/docs/man/nut-ipmipsu.txt +++ b/docs/man/nut-ipmipsu.txt @@ -116,5 +116,5 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * GNU FreeIPMI home page: http://www.gnu.org/software/freeipmi/ diff --git a/docs/man/nut-recorder.txt b/docs/man/nut-recorder.txt index edde4ae0bb..2758844d6d 100644 --- a/docs/man/nut-recorder.txt +++ b/docs/man/nut-recorder.txt @@ -77,4 +77,4 @@ linkman:dummy-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index 543e2f2ced..e45dd51720 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -254,4 +254,4 @@ linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nut.conf.txt b/docs/man/nut.conf.txt index 90f7106a41..0d4930520f 100644 --- a/docs/man/nut.conf.txt +++ b/docs/man/nut.conf.txt @@ -110,4 +110,4 @@ linkman:upsmon.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nutdrv_atcl_usb.txt b/docs/man/nutdrv_atcl_usb.txt index 77bdeb6b00..66ac7c9d60 100644 --- a/docs/man/nutdrv_atcl_usb.txt +++ b/docs/man/nutdrv_atcl_usb.txt @@ -92,4 +92,4 @@ linkman:nutdrv_qx[8] (`fuji` subdriver) Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index 633452c718..d5c6765266 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -152,7 +152,7 @@ The acceptable range is +60..599940+ seconds. The acceptable range is +12..5940+ seconds. *pins_shutdown_mode =* 'value':: -Set http://www.networkupstools.org/protocols/sola.html#_shutdown_set_command[shutdown mode functionality of Pin 1 and Pin 7] on the UPS DB9 communication port (Per Best Power's EPS-0059) to 'value' [+0..6+]. +Set https://www.networkupstools.org/protocols/sola.html#_shutdown_set_command[shutdown mode functionality of Pin 1 and Pin 7] on the UPS DB9 communication port (Per Best Power's EPS-0059) to 'value' [+0..6+]. MASTERGUARD PROTOCOL @@ -796,5 +796,5 @@ linkman:upsrw[8] Internet Resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ -* The NUT HCL: http://www.networkupstools.org/stable-hcl.html +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ +* The NUT HCL: https://www.networkupstools.org/stable-hcl.html diff --git a/docs/man/nutdrv_siemens_sitop.txt b/docs/man/nutdrv_siemens_sitop.txt index 854a38f883..6c95c52978 100644 --- a/docs/man/nutdrv_siemens_sitop.txt +++ b/docs/man/nutdrv_siemens_sitop.txt @@ -200,4 +200,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index 756ccf089c..38e64552a9 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -272,4 +272,4 @@ include::{builddir}/linkman-driver-names.txt[] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/oneac.txt b/docs/man/oneac.txt index beb257ebc7..dd38f126eb 100644 --- a/docs/man/oneac.txt +++ b/docs/man/oneac.txt @@ -128,4 +128,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/optiups.txt b/docs/man/optiups.txt index 1e1d90417a..740bd76b28 100644 --- a/docs/man/optiups.txt +++ b/docs/man/optiups.txt @@ -96,4 +96,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/phoenixcontact_modbus.txt b/docs/man/phoenixcontact_modbus.txt index e173089d61..a9f22cdc05 100644 --- a/docs/man/phoenixcontact_modbus.txt +++ b/docs/man/phoenixcontact_modbus.txt @@ -103,5 +103,5 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * libmodbus home page: http://libmodbus.org diff --git a/docs/man/pijuice.txt b/docs/man/pijuice.txt index 801646af60..bb87607279 100644 --- a/docs/man/pijuice.txt +++ b/docs/man/pijuice.txt @@ -85,4 +85,4 @@ Internet resources: * Product home page: https://uk.pi-supply.com/products/pijuice-standard -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/powercom.txt b/docs/man/powercom.txt index db7e936f7e..84b0bebd4c 100644 --- a/docs/man/powercom.txt +++ b/docs/man/powercom.txt @@ -229,4 +229,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/powerman-pdu.txt b/docs/man/powerman-pdu.txt index 5eeac31064..30d2fcda97 100644 --- a/docs/man/powerman-pdu.txt +++ b/docs/man/powerman-pdu.txt @@ -89,5 +89,5 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * The PowerMan home page: https://github.com/chaos/powerman diff --git a/docs/man/powerpanel.txt b/docs/man/powerpanel.txt index 4e8450d0bc..861d911eea 100644 --- a/docs/man/powerpanel.txt +++ b/docs/man/powerpanel.txt @@ -156,4 +156,4 @@ linkman:snmp-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/rhino.txt b/docs/man/rhino.txt index bdb30f892a..fe3ec333a8 100644 --- a/docs/man/rhino.txt +++ b/docs/man/rhino.txt @@ -62,4 +62,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/richcomm_usb.txt b/docs/man/richcomm_usb.txt index 4ee57e6006..527f7aa805 100644 --- a/docs/man/richcomm_usb.txt +++ b/docs/man/richcomm_usb.txt @@ -63,4 +63,4 @@ linkman:genericups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/riello_ser.txt b/docs/man/riello_ser.txt index cbc326b0a6..a9c684f51f 100644 --- a/docs/man/riello_ser.txt +++ b/docs/man/riello_ser.txt @@ -42,4 +42,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/riello_usb.txt b/docs/man/riello_usb.txt index 4301894e3a..737aa499f7 100644 --- a/docs/man/riello_usb.txt +++ b/docs/man/riello_usb.txt @@ -45,4 +45,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/safenet.txt b/docs/man/safenet.txt index 00aa02f929..136d2bfbbd 100644 --- a/docs/man/safenet.txt +++ b/docs/man/safenet.txt @@ -107,4 +107,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/skel.txt b/docs/man/skel.txt index 8e310943e0..286c101dd4 100644 --- a/docs/man/skel.txt +++ b/docs/man/skel.txt @@ -126,4 +126,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/snmp-ups.txt b/docs/man/snmp-ups.txt index 0f5f74cd0d..5f94d022c7 100644 --- a/docs/man/snmp-ups.txt +++ b/docs/man/snmp-ups.txt @@ -232,9 +232,9 @@ linkman:nutupsdrv[8] NUT SNMP Protocols Library ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Available at: http://www.networkupstools.org/ups-protocols.html#_snmp +Available at: https://www.networkupstools.org/ups-protocols.html#_snmp Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/sockdebug.txt b/docs/man/sockdebug.txt index c29ba100e5..f79bde71be 100644 --- a/docs/man/sockdebug.txt +++ b/docs/man/sockdebug.txt @@ -80,4 +80,4 @@ linkman:upsd[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/socomec_jbus.txt b/docs/man/socomec_jbus.txt index 0563668d56..8d0fecd552 100644 --- a/docs/man/socomec_jbus.txt +++ b/docs/man/socomec_jbus.txt @@ -160,7 +160,7 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * Socomec JBUS/Modbus Reference Guide: https://www.socomec.com/files/live/sites/systemsite/files/GB-JBUS-MODBUS-for-Delphys-MP-and-Delphys-MX-operating-manual.pdf * libmodbus home page: http://libmodbus.org diff --git a/docs/man/solis.txt b/docs/man/solis.txt index 532112b25a..d5e13830ca 100644 --- a/docs/man/solis.txt +++ b/docs/man/solis.txt @@ -70,4 +70,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/tripplite.txt b/docs/man/tripplite.txt index 9ec37f295d..8d104807fc 100644 --- a/docs/man/tripplite.txt +++ b/docs/man/tripplite.txt @@ -67,4 +67,4 @@ linkman:tripplitesu[8], linkman:tripplite_usb[8], linkman:usbhid-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/tripplite_usb.txt b/docs/man/tripplite_usb.txt index 92ea4834d4..252697a52c 100644 --- a/docs/man/tripplite_usb.txt +++ b/docs/man/tripplite_usb.txt @@ -180,4 +180,4 @@ regex(7), lsusb(8) Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/tripplitesu.txt b/docs/man/tripplitesu.txt index 9194a1229d..7272f52b39 100644 --- a/docs/man/tripplitesu.txt +++ b/docs/man/tripplitesu.txt @@ -50,4 +50,4 @@ linkman:tripplite[8], linkman:tripplite_usb[8], linkman:usbhid-ups[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index 314c2f7029..4c640d0aa0 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -319,4 +319,4 @@ linkman:upsdrvsvcctl[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsc.txt b/docs/man/upsc.txt index 2e89c5071a..1d4c8e4bda 100644 --- a/docs/man/upsc.txt +++ b/docs/man/upsc.txt @@ -118,4 +118,4 @@ linkman:upsd[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upscmd.txt b/docs/man/upscmd.txt index b8c80d8274..b60cab9843 100644 --- a/docs/man/upscmd.txt +++ b/docs/man/upscmd.txt @@ -110,4 +110,4 @@ linkman:upsd[8], linkman:upsrw[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upscode2.txt b/docs/man/upscode2.txt index 2044a08548..24afbacbfc 100644 --- a/docs/man/upscode2.txt +++ b/docs/man/upscode2.txt @@ -103,4 +103,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsd.conf.txt b/docs/man/upsd.conf.txt index 410910e99e..8287e54a56 100644 --- a/docs/man/upsd.conf.txt +++ b/docs/man/upsd.conf.txt @@ -155,4 +155,4 @@ linkman:upsd[8], linkman:nutupsdrv[8], linkman:upsd.users[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index eb2358c301..28918c3775 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -201,4 +201,4 @@ include::{builddir}/linkman-driver-names.txt[] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsd.users.txt b/docs/man/upsd.users.txt index 6b287d02e5..2a0889f2db 100644 --- a/docs/man/upsd.users.txt +++ b/docs/man/upsd.users.txt @@ -88,5 +88,5 @@ linkman:upsd[8], linkman:upsd.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index c9228fa1e3..446ed2d411 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -179,4 +179,4 @@ linkman:upsdrvsvcctl[8], linkman:nutupsdrv[8], linkman:upsd[8], linkman:ups.conf Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsdrvsvcctl.txt b/docs/man/upsdrvsvcctl.txt index 97855851fc..66dacdf866 100644 --- a/docs/man/upsdrvsvcctl.txt +++ b/docs/man/upsdrvsvcctl.txt @@ -204,4 +204,4 @@ linkman:nut-driver-enumerator[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsimage.cgi.txt b/docs/man/upsimage.cgi.txt index bdf23b83f6..d9f6b636f7 100644 --- a/docs/man/upsimage.cgi.txt +++ b/docs/man/upsimage.cgi.txt @@ -45,5 +45,5 @@ linkman:upsd[8], linkman:upsstats.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -* The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +* The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ * The gd home page: http://libgd.bitbucket.org diff --git a/docs/man/upslog.txt b/docs/man/upslog.txt index 882a13549c..1f0b64efc0 100644 --- a/docs/man/upslog.txt +++ b/docs/man/upslog.txt @@ -135,4 +135,4 @@ linkman:upsrw[8], linkman:upsmon[8], linkman:upssched[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsmon.conf.txt b/docs/man/upsmon.conf.txt index 1d4f6c3df4..2ebd18f419 100644 --- a/docs/man/upsmon.conf.txt +++ b/docs/man/upsmon.conf.txt @@ -432,4 +432,4 @@ linkman:upsmon[8], linkman:upsd[8], linkman:nutupsdrv[8]. Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index dc49d97ef5..6aa35d0ba3 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -519,4 +519,4 @@ linkman:upsset.cgi[8], linkman:upsstats.cgi[8], linkman:upsimage.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsrw.txt b/docs/man/upsrw.txt index ebcd2056d1..7e93d02d1f 100644 --- a/docs/man/upsrw.txt +++ b/docs/man/upsrw.txt @@ -124,4 +124,4 @@ linkman:upsd[8], linkman:upscmd[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upssched.conf.txt b/docs/man/upssched.conf.txt index 52a028c77d..f6ea00e457 100644 --- a/docs/man/upssched.conf.txt +++ b/docs/man/upssched.conf.txt @@ -108,4 +108,4 @@ linkman:upssched[8], linkman:upsmon[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upssched.txt b/docs/man/upssched.txt index b5830701f9..44cdb3d9ae 100644 --- a/docs/man/upssched.txt +++ b/docs/man/upssched.txt @@ -133,4 +133,4 @@ linkman:upsmon[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsset.cgi.txt b/docs/man/upsset.cgi.txt index 78912dda12..3bae6a1d5c 100644 --- a/docs/man/upsset.cgi.txt +++ b/docs/man/upsset.cgi.txt @@ -95,4 +95,4 @@ SEE ALSO Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsset.conf.txt b/docs/man/upsset.conf.txt index 6fab07a7e3..cfb422928d 100644 --- a/docs/man/upsset.conf.txt +++ b/docs/man/upsset.conf.txt @@ -74,4 +74,4 @@ linkman:upsset.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsstats.cgi.txt b/docs/man/upsstats.cgi.txt index e79e5395ca..0c6435b539 100644 --- a/docs/man/upsstats.cgi.txt +++ b/docs/man/upsstats.cgi.txt @@ -60,4 +60,4 @@ linkman:upsimage.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/upsstats.html.txt b/docs/man/upsstats.html.txt index ec869f480a..91c4e7bf6e 100644 --- a/docs/man/upsstats.html.txt +++ b/docs/man/upsstats.html.txt @@ -233,4 +233,4 @@ linkman:upsstats.cgi[8], linkman:upsimage.cgi[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index 5a93a16925..9b86737991 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -293,4 +293,4 @@ linkman:nutupsdrv[8] Internet resources ~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/man/victronups.txt b/docs/man/victronups.txt index 17be94d7aa..d51d09f9c8 100644 --- a/docs/man/victronups.txt +++ b/docs/man/victronups.txt @@ -66,4 +66,4 @@ linkman:nutupsdrv[8] Internet resources: ~~~~~~~~~~~~~~~~~~~ -The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/new-clients.txt b/docs/new-clients.txt index 1b07900071..48cff0660e 100644 --- a/docs/new-clients.txt +++ b/docs/new-clients.txt @@ -40,7 +40,7 @@ functions documentation referenced in the same file. Clients like upsc are provided as examples of how to retrieve data using the upsclient functions. -link:http://www.networkupstools.org/projects.html[Other programs] not included +link:https://www.networkupstools.org/projects.html[Other programs] not included in this package may also use this library, such as wmnut. High level library: libnutclient diff --git a/docs/nut-names.txt b/docs/nut-names.txt index 873fe09c64..af804d2ec4 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -732,7 +732,7 @@ server: Internal server information |=============================================================================== | Name | Description | Example value | server.info | Server information | Network UPS Tools upsd vX.Y.Z - - http://www.networkupstools.org/ + https://www.networkupstools.org/ | server.version | Server version | X.Y.Z |=============================================================================== diff --git a/docs/security.txt b/docs/security.txt index 09c101cf4f..535d3b7293 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -22,15 +22,15 @@ How to verify the NUT source code signature In order to verify the NUT source code signature for releases, perform the following steps: -- Retrieve the link:http://www.networkupstools.org/download.html[NUT source code] +- Retrieve the link:https://www.networkupstools.org/download.html[NUT source code] (nut-X.Y.Z.tar.gz) and the matching signature (nut-X.Y.Z.tar.gz.sig) -- Retrieve the link:http://www.networkupstools.org/source/nut-key.gpg[NUT maintainer's signature]: +- Retrieve the link:https://www.networkupstools.org/source/nut-key.gpg[NUT maintainer's signature]: - $ gpg --fetch-keys http://www.networkupstools.org/source/nut-key.gpg + $ gpg --fetch-keys https://www.networkupstools.org/source/nut-key.gpg NOTE: As of NUT 2.7.3, a new release key is used. In order to verify a previous release, please use -link:http://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's signature] +link:https://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's signature] - Launch the GPG checking using the following command: diff --git a/docs/snmp.txt b/docs/snmp.txt index 64b9c06f6f..0e058761dd 100644 --- a/docs/snmp.txt +++ b/docs/snmp.txt @@ -47,4 +47,4 @@ manpage (man 8 snmp-ups). References: - NUT SNMP Protocols Library Available at: -http://www.networkupstools.org/ups-protocols.html#_snmp +https://www.networkupstools.org/ups-protocols.html#_snmp diff --git a/docs/support.txt b/docs/support.txt index c7d6165bcb..f0e2de46f6 100644 --- a/docs/support.txt +++ b/docs/support.txt @@ -145,4 +145,4 @@ To report new Devices Dumps Library entries, posting an issue is okay, but posting a link:https://github.com/networkupstools/nut-ddl/pulls[pull request] is a lot better -- easier for maintainers to review and merge any time. For some more detailed instructions about useful DDL reports, please see -link:https://networkupstools.org/ddl/#_file_naming_convention[NUT DDL page]. +link:https://www.networkupstools.org/ddl/#_file_naming_convention[NUT DDL page]. diff --git a/docs/user-manual.txt b/docs/user-manual.txt index 0e96ea4e25..638f113e87 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -147,7 +147,7 @@ include::nut-names.txt[] Appendix D: Hardware Compatibility List ======================================= -Refer to the link:http://www.networkupstools.org/stable-hcl.html[online HCL]. +Refer to the link:https://www.networkupstools.org/stable-hcl.html[online HCL]. Appendix E: Documentation diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 261b18f5f7..0eea5ad9dd 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -2082,7 +2082,7 @@ void upsdrv_help(void) printf( "\nFor detailed information, please refer to:\n" " - apcsmart(8)\n" - " - http://www.networkupstools.org/docs/man/apcsmart.html\n" + " - https://www.networkupstools.org/docs/man/apcsmart.html\n" ); } diff --git a/drivers/blazer.c b/drivers/blazer.c index 1d6209fbf2..0960fa96bb 100644 --- a/drivers/blazer.c +++ b/drivers/blazer.c @@ -7,7 +7,7 @@ * device support from such legacy drivers over time. * * A document describing the protocol implemented by this driver can be - * found online at http://www.networkupstools.org/ups-protocols/megatec.html + * found online at https://www.networkupstools.org/ups-protocols/megatec.html * * Copyright (C) * 2008,2009 - Arjen de Korte diff --git a/drivers/blazer.h b/drivers/blazer.h index 6a8c71c24e..67597d5b4e 100644 --- a/drivers/blazer.h +++ b/drivers/blazer.h @@ -7,7 +7,7 @@ * device support from such legacy drivers over time. * * A document describing the protocol implemented by this driver can be - * found online at "http://www.networkupstools.org/protocols/megatec.html". + * found online at "https://www.networkupstools.org/protocols/megatec.html". * * Copyright (C) 2008 - Arjen de Korte * diff --git a/drivers/blazer_ser.c b/drivers/blazer_ser.c index 6d82bbfce7..1fd9fee71a 100644 --- a/drivers/blazer_ser.c +++ b/drivers/blazer_ser.c @@ -7,7 +7,7 @@ * device support from such legacy drivers over time. * * A document describing the protocol implemented by this driver can be - * found online at "http://www.networkupstools.org/protocols/megatec.html". + * found online at "https://www.networkupstools.org/protocols/megatec.html". * * Copyright (C) 2008 - Arjen de Korte * diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 74d0710b84..d8aee6c221 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -7,7 +7,7 @@ * device support from such legacy drivers over time. * * A document describing the protocol implemented by this driver can be - * found online at "http://www.networkupstools.org/protocols/megatec.html". + * found online at "https://www.networkupstools.org/protocols/megatec.html". * * Copyright (C) 2003-2009 Arjen de Korte * Copyright (C) 2011-2012 Arnaud Quette diff --git a/drivers/delta_ups-mib.c b/drivers/delta_ups-mib.c index 08b810439d..888542aef8 100644 --- a/drivers/delta_ups-mib.c +++ b/drivers/delta_ups-mib.c @@ -6,7 +6,7 @@ * Note: this subdriver was initially generated as a "stub" by the * gen-snmp-subdriver.sh script. It must be customized! * - * MIB reference: http://www.networkupstools.org/ups-protocols/snmp/DeltaUPSv4.mib + * MIB reference: https://www.networkupstools.org/ups-protocols/snmp/DeltaUPSv4.mib * * 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 diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index b5f5a8b7fc..94b9af7a01 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -451,7 +451,7 @@ static snmp_info_t eaton_marlin_mib[] = { /* FIXME: * - Voltage is only measured per phase, as mV! * so input.voltage == input.L1.voltage for both single and 3phase - * - As per NUT namespace (http://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts) + * - As per NUT namespace (https://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts) * Voltage has to be expressed either phase-phase or phase-neutral * This is depending on OID inputVoltageMeasType * INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7) diff --git a/drivers/hpe-pdu-mib.c b/drivers/hpe-pdu-mib.c index 0193f619ba..3f6c7dce70 100644 --- a/drivers/hpe-pdu-mib.c +++ b/drivers/hpe-pdu-mib.c @@ -277,7 +277,7 @@ static snmp_info_t hpe_pdu_mib[] = { /* FIXME: * - Voltage is only measured per phase, as mV! * so input.voltage == input.L1.voltage for both single and 3phase - * - As per NUT namespace (http://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts) + * - As per NUT namespace (https://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts) * Voltage has to be expressed either phase-phase or phase-neutral * This is depending on OID inputVoltageMeasType * INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7) diff --git a/drivers/libhid.c b/drivers/libhid.c index 6cd2052359..3999feca46 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -12,7 +12,7 @@ * * The logic of this file is ripped from mge-shut driver (also from * Arnaud Quette), which is a "HID over serial link" UPS driver for - * Network UPS Tools + * Network UPS Tools * * 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 diff --git a/drivers/libusb0.c b/drivers/libusb0.c index ef94d6ca33..b07a363c0c 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -10,7 +10,7 @@ * * The logic of this file is ripped from mge-shut driver (also from * Arnaud Quette), which is a "HID over serial link" UPS driver for - * Network UPS Tools + * Network UPS Tools * * 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 diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 530633bf6a..522d8a183d 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -8,7 +8,7 @@ * * The logic of this file is ripped from mge-shut driver (also from * Arnaud Quette), which is a "HID over serial link" UPS driver for - * Network UPS Tools + * Network UPS Tools * * 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 diff --git a/drivers/nut_libusb.h b/drivers/nut_libusb.h index b7906d2ce8..8b2a644341 100644 --- a/drivers/nut_libusb.h +++ b/drivers/nut_libusb.h @@ -11,7 +11,7 @@ * * The logic of this file is ripped from mge-shut driver (also from * Arnaud Quette), which is a "HID over serial link" UPS driver for - * Network UPS Tools + * Network UPS Tools * * 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 diff --git a/drivers/optiups.c b/drivers/optiups.c index ade3441d65..f0cf05512f 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -62,7 +62,7 @@ upsdrv_info_t upsdrv_info = { "It works even with a pl2303 usb-serial converter." "\n" \ "**********************************************************" "\n" -/* See http://www.networkupstools.org/protocols/optiups.html and the end of this +/* See https://www.networkupstools.org/protocols/optiups.html and the end of this * file for more information on the cable and the OPTI-UPS serial protocol used on * at least the older OPTI UPS models (420E, 820ES). */ diff --git a/drivers/riello.c b/drivers/riello.c index 48cc1cd1db..fe1de5c905 100644 --- a/drivers/riello.c +++ b/drivers/riello.c @@ -4,8 +4,8 @@ * Documents describing the protocol implemented by this driver can be * found online at: * - * https://networkupstools.org/protocols/riello/PSGPSER-0104.pdf - * https://networkupstools.org/protocols/riello/PSSENTR-0100.pdf + * https://www.networkupstools.org/protocols/riello/PSGPSER-0104.pdf + * https://www.networkupstools.org/protocols/riello/PSSENTR-0100.pdf * * Copyright (C) 2012 - Elio Parisi * diff --git a/drivers/riello.h b/drivers/riello.h index a2ab948701..e513f638b2 100644 --- a/drivers/riello.h +++ b/drivers/riello.h @@ -4,8 +4,8 @@ * Documents describing the protocol implemented by this driver can be * found online at: * - * https://networkupstools.org/protocols/riello/PSGPSER-0104.pdf - * https://networkupstools.org/protocols/riello/PSSENTR-0100.pdf + * https://www.networkupstools.org/protocols/riello/PSGPSER-0104.pdf + * https://www.networkupstools.org/protocols/riello/PSSENTR-0100.pdf * * Copyright (C) 2012 - Elio Parisi * diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index cd3b8a997e..8238a9ec17 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -2,8 +2,8 @@ * riello_ser.c: support for Riello serial protocol based UPSes * * A document describing the protocol implemented by this driver can be - * found online at "https://networkupstools.org/protocols/riello/PSGPSER-0104.pdf" - * and "https://networkupstools.org/protocols/riello/PSSENTR-0100.pdf". + * found online at "https://www.networkupstools.org/protocols/riello/PSGPSER-0104.pdf" + * and "https://www.networkupstools.org/protocols/riello/PSSENTR-0100.pdf". * * Copyright (C) 2012 - Elio Parisi * diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index f6047129b9..e13e1d2655 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -4,7 +4,7 @@ * A document describing the protocol implemented by this driver can be * found online at: * - * https://networkupstools.org/protocols/riello/PSGPSER-0104.pdf + * https://www.networkupstools.org/protocols/riello/PSGPSER-0104.pdf * * Copyright (C) 2012 - Elio Parisi * Copyright (C) 2016 Eaton diff --git a/indent.sh b/indent.sh index 4c1826f309..0aaf571f32 100755 --- a/indent.sh +++ b/indent.sh @@ -1,7 +1,7 @@ #!/bin/bash # Filter NUT C source file style to conform to recommendations of -# http://networkupstools.org/docs/developer-guide.chunked/ar01s03.html#_coding_style +# https://www.networkupstools.org/docs/developer-guide.chunked/ar01s03.html#_coding_style # Note that the sed filter "command does a reasonable job of converting # most C++ style comments (but not URLs and DOCTYPE strings)" so a manual # pass may be needed to revise the changes. diff --git a/scripts/Aix/nut-aix.spec.in b/scripts/Aix/nut-aix.spec.in index 37e4934745..1302160dcf 100644 --- a/scripts/Aix/nut-aix.spec.in +++ b/scripts/Aix/nut-aix.spec.in @@ -17,8 +17,8 @@ Release: 1 Group: Applications/System License: GPLv2+ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Url: http://www.networkupstools.org/ -Source: http://www.networkupstools.org/source/@TREE_VERSION@/%{name}-%{version}.tar.gz +Url: https://www.networkupstools.org/ +Source: https://www.networkupstools.org/source/@TREE_VERSION@/%{name}-%{version}.tar.gz Source1: nut.init #Source2: ups.sysconfig #Source3: nut-client.tmpfiles diff --git a/scripts/Solaris/pkginfo.in b/scripts/Solaris/pkginfo.in index 39667f0a79..2cbbb3fb42 100644 --- a/scripts/Solaris/pkginfo.in +++ b/scripts/Solaris/pkginfo.in @@ -3,7 +3,7 @@ NAME="Network UPS Tools" ARCH="@target_cpu@" VERSION="@PACKAGE_VERSION@" CATEGORY="application" -VENDOR="http://www.networkupstools.org" +VENDOR="https://www.networkupstools.org" EMAIL=" " PSTAMP=" " DESCRIPTION="Network UPS Tools (NUT) is a client/server monitoring system that allows computers to share uninterruptible power supply (UPS) and power distribution unit (PDU) hardware. Clients access the hardware through the server, and are notified whenever the power status changes." diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh index f4d7b28046..b557ace3c6 100755 --- a/scripts/Windows/build-mingw-nut.sh +++ b/scripts/Windows/build-mingw-nut.sh @@ -38,7 +38,7 @@ stable) # Stable version (download the latest stable archive) VER_OPT_SHORT="`echo "$VER_OPT" | awk -F. '{print $1"."$2}'`" if [ ! -s nut-$VER_OPT.tar.gz ] ; then - wget http://www.networkupstools.org/source/$VER_OPT_SHORT/nut-$VER_OPT.tar.gz + wget https://www.networkupstools.org/source/$VER_OPT_SHORT/nut-$VER_OPT.tar.gz fi rm -rf nut-$VER_OPT tar -xzf nut-$VER_OPT.tar.gz diff --git a/scripts/perl/Nut.pm b/scripts/perl/Nut.pm index f4f81f27f6..25d56dba21 100644 --- a/scripts/perl/Nut.pm +++ b/scripts/perl/Nut.pm @@ -728,7 +728,7 @@ Nut - a module to talk to a UPS via NUT (Network UPS Tools) upsd This is an object-oriented (whoo!) interface between Perl and upsd from the Network UPS Tools package version 1.5 and above -(http://www.networkupstools.org/). +(https://www.networkupstools.org/). Note that it only talks to upsd for you in a Perl-ish way. It doesn't monitor the UPS continously. diff --git a/scripts/python/app/locale/NUT-Monitor.pot b/scripts/python/app/locale/NUT-Monitor.pot index caf9c6687c..d36e61af28 100644 --- a/scripts/python/app/locale/NUT-Monitor.pot +++ b/scripts/python/app/locale/NUT-Monitor.pot @@ -358,7 +358,7 @@ msgid "" "For more information about NUT (Network UPS Tools)\n" "please visit the author's website.\n" "\n" -"http://www.networkupstools.org\n" +"https://www.networkupstools.org\n" msgstr "" #: gui-1.3.glade.h:37 diff --git a/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo index ede50eb2529236c1499497cce963ad20c89844ad..bf2a9ab3f15b99e0b33225878da9bff30b04dadd 100644 GIT binary patch delta 21 bcmaEE^wMZUC=X-t=1`t^E+Dl!8UNi^Y delta 17 ZcmaE9^xSAeD9`3Fo_Ma!+r&0A0RTmr2KWE~ diff --git a/scripts/python/app/locale/fr/fr.po b/scripts/python/app/locale/fr/fr.po index e46edd64b2..29a71a77f8 100644 --- a/scripts/python/app/locale/fr/fr.po +++ b/scripts/python/app/locale/fr/fr.po @@ -375,14 +375,14 @@ msgid "" "For more information about NUT (Network UPS Tools)\n" "please visit the author's website.\n" "\n" -"http://www.networkupstools.org\n" +"https://www.networkupstools.org\n" msgstr "" "Interface pour gérer les onduleurs connectés à un serveur NUT.\n" "\n" "Pour plus d'informations sur NUT (Network UPS Tools)\n" "veuillez consulter le site de l'auteur.\n" "\n" -"http://www.networkupstools.org\n" +"https://www.networkupstools.org\n" #: gui-1.3.glade.h:37 msgid "http://www.lestat.st" diff --git a/scripts/python/app/locale/it/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/it/LC_MESSAGES/NUT-Monitor.mo index 5a95c22f1344669e32d5ab1a083071911a22e2f5..e7d3d43d49392faf587e0ff2ed85266fe953e80e 100644 GIT binary patch delta 25 hcmdmIbiioCRc^-O%~!c=xfqKlU*%TcTq$;x2>^^&3K#$Y delta 21 dcmX?Lw9jb6RqoB#xNEs4U*lHaTrGB#2>@<72{Zrz diff --git a/scripts/python/app/locale/it/it.po b/scripts/python/app/locale/it/it.po index ada6329947..da0287090e 100644 --- a/scripts/python/app/locale/it/it.po +++ b/scripts/python/app/locale/it/it.po @@ -375,14 +375,14 @@ msgid "" "For more information about NUT (Network UPS Tools)\n" "please visit the author's website.\n" "\n" -"http://www.networkupstools.org\n" +"https://www.networkupstools.org\n" msgstr "" "Interfaccia grafica per gestire dispositivi connessi a un server di NUT.\n" "\n" "Per maggiori informazioni su NUT (Network UPS Tools)\n" "si visiti il sito dell'autore.\n" "\n" -"http://www.networkupstools.org\n" +"https://www.networkupstools.org\n" #: gui-1.3.glade.h:37 msgid "http://www.lestat.st" diff --git a/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo index 89ee0208324ba5ec91a87649b6ba198a16eef1b3..e5c3c6dfe3497a2339a532cd338efd5394b9381e 100644 GIT binary patch delta 21 bcmccMe#w1<h1>NUT-Monitor 1.3.1</h1> <p>GUI to manage devices connected a NUT server.</p> <p>For more information about NUT (Network UPS Tools) please visit the author's website.</p> -<p style="margin-bottom: 1.5em">http://www.networkupstools.org</p> +<p style="margin-bottom: 1.5em">https://www.networkupstools.org</p> <p style=" font-size:8pt;">Copyright (c) 2010 David Goncalves</p> <p><a href="http://www.lestat.st/informatique/projets/nut-monitor-en">http://www.lestat.st</a></p>
diff --git a/scripts/python/app/ui/gui-1.3.glade b/scripts/python/app/ui/gui-1.3.glade index eb42aba3b0..5ab1f72836 100644 --- a/scripts/python/app/ui/gui-1.3.glade +++ b/scripts/python/app/ui/gui-1.3.glade @@ -1028,7 +1028,7 @@ want to delete from list... For more information about NUT (Network UPS Tools) please visit the author's website. -http://www.networkupstools.org +https://www.networkupstools.org http://www.lestat.st/informatique/projets/nut-monitor-en http://www.lestat.st diff --git a/scripts/python/app/ui/gui-1.3.glade.h b/scripts/python/app/ui/gui-1.3.glade.h index 8b9c95f164..33c3d4ecdd 100644 --- a/scripts/python/app/ui/gui-1.3.glade.h +++ b/scripts/python/app/ui/gui-1.3.glade.h @@ -32,7 +32,7 @@ char *s = N_("GUI to manage devices connected a NUT server.\n" "For more information about NUT (Network UPS Tools)\n" "please visit the author's website.\n" "\n" - "http://www.networkupstools.org\n" + "https://www.networkupstools.org\n" ""); char *s = N_("http://www.lestat.st"); char *s = N_("Copyright (C) 2010 David Goncalves \n" diff --git a/server/netget.c b/server/netget.c index a5f822a569..c2a31fa354 100644 --- a/server/netget.c +++ b/server/netget.c @@ -165,7 +165,7 @@ static void get_var_server(nut_ctype_t *client, const char *upsname, const char if (!strcasecmp(var, "server.info")) { sendback(client, "VAR %s server.info " "\"Network UPS Tools upsd %s - " - "http://www.networkupstools.org/\"\n", + "https://www.networkupstools.org/\"\n", upsname, UPS_VERSION); return; } diff --git a/server/netmisc.c b/server/netmisc.c index 106d828709..ec4e8d28df 100644 --- a/server/netmisc.c +++ b/server/netmisc.c @@ -37,7 +37,7 @@ void net_ver(nut_ctype_t *client, size_t numarg, const char **arg) return; } - sendback(client, "Network UPS Tools upsd %s - http://www.networkupstools.org/\n", + sendback(client, "Network UPS Tools upsd %s - https://www.networkupstools.org/\n", UPS_VERSION); } diff --git a/tools/nut-ddl-dump.sh b/tools/nut-ddl-dump.sh index 326a06daa2..d006b693c7 100755 --- a/tools/nut-ddl-dump.sh +++ b/tools/nut-ddl-dump.sh @@ -8,7 +8,7 @@ # FIXME: # - check if a previous report exists, and increase report number #  - we currently use the .dev format ; but also consider the NDS format -# http://www.networkupstools.org/ddl/ +# https://www.networkupstools.org/ddl/ ################################################################################ strUsage="Usage: $0 " diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index bba85ccf1c..20d72934e4 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -116,7 +116,7 @@ sub gen_usb_files my $out_devd = do {local *OUT_DEVD}; open $out_devd, ">$output_devd" || die "error $output_devd : $!"; print $out_devd '# This file is generated and installed by the Network UPS Tools package.'."\n"; - print $out_devd "# Homepage: http://www.networkupstools.org/\n\n"; + print $out_devd "# Homepage: https://www.networkupstools.org/\n\n"; # UPower file header my $outUPower = do {local *OUT_UPOWER}; From 0c852a7dbf5f9ce0b9a85dbf65efad554da1d83a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 22:06:44 +0200 Subject: [PATCH 0840/1232] docs/security.txt: clarify that GPG tool output varied over eons --- docs/security.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security.txt b/docs/security.txt index 535d3b7293..390e7e76e3 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -36,7 +36,8 @@ link:https://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's $ gpg --verify nut-X.Y.Z.tar.gz.sig -- You should see a message mentioning a "Good signature", like: +- You should see a message mentioning a "Good signature", with formatting which + depends on your gpg version, like: gpg: Signature made Wed Apr 15 15:55:30 2015 CEST using RSA key ID 55CA5976 gpg: Good signature from "Arnaud Quette ..." From 4be5c2a29e193a42318612f129f1bcf9a7676b6a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 23:09:07 +0200 Subject: [PATCH 0841/1232] docs/security.txt, docs/nut.dict: update "verifySourceSig" chapter with new GPG key set for "Jim Klimov ..." DE0184DA7043DCF7 [#1963] --- docs/nut.dict | 5 ++++- docs/security.txt | 35 +++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/docs/nut.dict b/docs/nut.dict index f37f281e5e..2d21fa1dfd 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3176 utf-8 +personal_ws-1.1 en 3179 utf-8 AAS ABI ACFAIL @@ -2147,6 +2147,7 @@ kVA kadets kaminski kde +keychain keyclick keygen keyout @@ -2928,6 +2929,7 @@ tios tmp tmpfiles tmpfs +tmpring toolchain toolkits topbot @@ -2970,6 +2972,7 @@ udev udevadm ufw ugen +uid uint ukUNV ul diff --git a/docs/security.txt b/docs/security.txt index 390e7e76e3..f0fb2a2178 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -24,13 +24,27 @@ following steps: - Retrieve the link:https://www.networkupstools.org/download.html[NUT source code] (nut-X.Y.Z.tar.gz) and the matching signature (nut-X.Y.Z.tar.gz.sig) -- Retrieve the link:https://www.networkupstools.org/source/nut-key.gpg[NUT maintainer's signature]: +- Retrieve the link:https://www.networkupstools.org/source/nut-key.gpg[NUT +maintainer's signature keyring]: $ gpg --fetch-keys https://www.networkupstools.org/source/nut-key.gpg -NOTE: As of NUT 2.7.3, a new release key is used. In order to verify a previous -release, please use -link:https://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's signature] +NOTE: As of NUT 2.8.0, a new release key is used, but the `nut-key.gpg` should +be cumulative with older chain key files (includes them). You can view the key +list in a downloaded copy of the URL above with: ++ + $ gpg --with-colons --import-options import-show --dry-run --import < nut-key.gpg ++ +and as of this writing, it should contain two key sets for various identities +of "Arnaud Quette" and one set of "Jim Klimov". + +Just in case, the previous key file used since NUT 2.7.3 release is stored as +link:https://www.networkupstools.org/source/nut-key-2.7.3.gpg[NUT +old maintainer's signature for 2.7.3-2.7.4 releases] + +In order to verify an even older release, please use +link:https://www.networkupstools.org/source/nut-old-key.gpg[NUT +old maintainer's signature since 2002 until 2.7.3 release] - Launch the GPG checking using the following command: @@ -39,12 +53,21 @@ link:https://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's - You should see a message mentioning a "Good signature", with formatting which depends on your gpg version, like: + gpg: Signature made Thu Jun 1 00:10:16 2023 CEST + ... + gpg: Good signature from "Jim Klimov ..." + ... + Primary key fingerprint: B834 59F7 76B9 0224 988F 36C0 DE01 84DA 7043 DCF7 + ... + +NOTE: the previously used maintainer's signatures would output (with markup of +older gpg tools here): ++ gpg: Signature made Wed Apr 15 15:55:30 2015 CEST using RSA key ID 55CA5976 gpg: Good signature from "Arnaud Quette ..." ... - -NOTE: the previously used maintainer's signature would output: + +or: gpg: Signature made Thu Jul 5 16:15:05 2007 CEST using DSA key ID 204DDF1B gpg: Good signature from "Arnaud Quette ..." ... From 36e4769e9f502ac2d44320403006cf0951bf095e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 23:09:35 +0200 Subject: [PATCH 0842/1232] docs/security.txt: add maintainer notes on updating nut-key.gpg [#1963] --- docs/security.txt | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/security.txt b/docs/security.txt index f0fb2a2178..c1a6fb37c1 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -72,6 +72,43 @@ or: gpg: Good signature from "Arnaud Quette ..." ... +//////// +Maintainer notes for posterity: + +* See https://github.com/networkupstools/nut/issues/1963 and + https://github.com/networkupstools/nut/issues/1410 for recent + forays into this area. + +* Repo is https://github.com/networkupstools/nut-source-archive.git + +* Keys in the file can be viewed with: +---- +:; gpg --with-colons --import-options import-show --dry-run --import < nut-key.gpg +---- + +* Old keys as well as a new maintainer key can be imported first into + a temporary keyring (existing target file and a slash in its path + name argument are allegedly important): +---- +:; rm -f tmpring.gpg ; touch tmpring.gpg +:; gpg --no-default-keyring --keyring ./tmpring.gpg --import nut-key.gpg +:; gpg --no-default-keyring --keyring ./tmpring.gpg --import nut-old-key.gpg +:; gpg --no-default-keyring --keyring ./tmpring.gpg --import nut-key-2.7.3.gpg +:; gpg --no-default-keyring --keyring ./tmpring.gpg --import ~/.gnupg/HEXCODEMYNEWKEYDATA.pub +---- + +** Note that whenever the key owner edits the primary key data, e.g. to add or + remove "uid" entries with e-mail aliases, or sub-keys dedicated for specific + purposes, the `~/.gnupg/HEXCODEMYNEWKEYDATA.pub` is changed and should be + re-published to OpenPGP servers, to nut-website, to GitHub account, etc. + +* This (binary) keychain can be exported into ASCII-armor format, and also + update the keychain file used by default: +---- +:; gpg --no-default-keyring --keyring ./tmpring.gpg --export -a > nut-key.gpg +---- +//////// + System level privileges and ownership ------------------------------------- From 1d73aac6a68f1c472b7ec9adf1d3d3166f0e9c80 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jun 2023 23:35:59 +0200 Subject: [PATCH 0843/1232] docs/security.txt, docs/nut.dict: add a chapter on checksum file verification [#1963] --- docs/nut.dict | 8 +++++++- docs/security.txt | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 2d21fa1dfd..beb250a03d 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3179 utf-8 +personal_ws-1.1 en 3185 utf-8 AAS ABI ACFAIL @@ -645,6 +645,7 @@ MAXPARMAKES MBATTCHG MCOL MCU +MDigest MEC MEGATAEC MH @@ -1586,6 +1587,7 @@ bestfort bestfortress bestuferrups bestups +bfe bigbox bigone bigserver @@ -1633,6 +1635,7 @@ cblimit ccache cd cdc +cdf centos cerr certfile @@ -1662,6 +1665,7 @@ chargermode chargetime charset checksum +checksums chgrp chipset chkconfig @@ -1911,6 +1915,7 @@ fallthrough fatalx faultsensitivity fc +fcb fcntl fd fds @@ -2751,6 +2756,7 @@ setvar's sfr sgml sgs +sha shm shutdownArguments shutdowndebounce diff --git a/docs/security.txt b/docs/security.txt index c1a6fb37c1..6d54fb71df 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -109,6 +109,44 @@ Maintainer notes for posterity: ---- //////// +How to verify the NUT source code checksum +------------------------------------------ + +As a weaker but simpler alternative to verifying a *signature*, you can verify +just the accompanying checksums of the source archive file. This is useful +primarily to check against bit-rot in original storage or in transit. As far +as disclaimers go: ideally, you should cover all provided algorithms -- e.g. +MD5 and SHA256 -- to minimize the chance that intentional malicious tampering +on the wire goes undetected. A myriad tools can check that on various platforms; +some examples follow: + + # Example original checksum to compare with, from NUT website: + $ cat nut-2.8.0.tar.gz.sha256 + c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 nut-2.8.0.tar.gz + + # Generate checksum of downloaded archive with perl (a NUT build dependency + # generally, though you may have to install Digest::SHA module from CPAN): + $ perl -MDigest::SHA=sha256_hex -le "print sha256_hex <>" nut-2.8.0.tar.gz + c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 + + # Generate checksum of downloaded archive with openssl (another optional + # NUT build dependency): + $ openssl sha256 nut-2.8.0.tar.gz + SHA256(nut-2.8.0.tar.gz)= c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 + + # Generate checksum of downloaded archive with coreutils: + $ sha256sum nut-2.8.0.tar.gz + c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 nut-2.8.0.tar.gz + + # Auto-check downloaded checksum against downloaded archive with coreutils: + $ sha256sum -c nut-2.8.0.tar.gz.sha256 + nut-2.8.0.tar.gz: OK + + # Generate checksum of downloaded archive with GPG: + $ gpg --print-md SHA256 nut-2.8.0.tar.gz + nut-2.8.0.tar.gz: C3E5A708 DA797B7C 70B653D3 7B1206A0 + 00FCB503 B85519FE 4CDF6353 F792BFE5 + System level privileges and ownership ------------------------------------- From 9ce3f8ac60af4b151db6a2b4a2faa952d2b50977 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 1 Jul 2023 01:13:37 +0200 Subject: [PATCH 0844/1232] scripts/python/Makefile.am, configure.ac, docs/config-prereqs.txt: use gettext msgfmt to compile binary translation files --- configure.ac | 6 ++++++ docs/config-prereqs.txt | 9 +++++++++ docs/nut.dict | 6 +++++- scripts/python/Makefile.am | 17 ++++++++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 22525dfb98..f9b376e14f 100644 --- a/configure.ac +++ b/configure.ac @@ -1558,6 +1558,12 @@ dnl installing these features or not. dnl Note: more for tests than other reasons, there is also an option dnl value to "force" the installation. +dnl The gettext "msgfmt" tool (or equivalent) can be used to maintain +dnl human-language text translations. Currently this is used specifically +dnl in the Python NUT-Monitor app sources (*.po => *.mo conversions). +AC_PATH_PROGS([MSGFMT], [msgfmt], [none]) +AM_CONDITIONAL([HAVE_MSGFMT], [test "x${MSGFMT}" != "xnone"]) + dnl ---------------------------------------------------------------------- dnl checks related to --with-serial diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 43d33802f9..51f3b84c77 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -141,6 +141,15 @@ metadata about recently published package revisions: # :; apt-get install python3 python3.9 # You can find a list of what is (pre-)installed with: # :; dpkg -l | grep -Ei 'perl|python' +# +# For localization maintenance (currently in Python NUT-Monitor app), +# provide an `msgfmt` implementation, e.g.: +# :; apt-get install gettext +# +# To install the Python NUT-Monitor app, you may need some modules: +# :; apt-get install pip +# For Python3: +# :; pip install PyQt5 configparser # For spell-checking, highly recommended if you would propose pull requests: :; apt-get install \ diff --git a/docs/nut.dict b/docs/nut.dict index beb250a03d..025c5be327 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3185 utf-8 +personal_ws-1.1 en 3189 utf-8 AAS ABI ACFAIL @@ -976,6 +976,7 @@ PwrOut PyGTK PyNUT PyNUTClient +PyQt QBDR QBT QBV @@ -1710,6 +1711,7 @@ compat compilerPath conf config +configparser configs configurationProvider configureaz @@ -1983,6 +1985,7 @@ getconf getent getenv getopt +gettext getvar gitcache github @@ -2358,6 +2361,7 @@ monuser morbo mozilla msec +msgfmt msi msvcrt msys diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 542989d82c..dfbedca182 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -24,6 +24,10 @@ PYTHON3_SITE_PACKAGES = @PYTHON3_SITE_PACKAGES@ BINDIR = @BINDIR@ +if HAVE_MSGFMT +MSGFMT = @MSGFMT@ +endif HAVE_MSGFMT + NUT_MONITOR_PY2GTK2 = \ app/ui/gui-1.3.glade \ app/nut-monitor-py2gtk2.desktop @@ -71,7 +75,7 @@ PYNUT_COMMON = \ module/README # Note: we both distribute and install the generated *.mo translation files -# so they are listed above and not in NUT_MONITOR_COMMON_GENERATED +# so they are listed above and not in NUT_MONITOR_COMMON_TEMPLATE NUT_MONITOR_COMMON_TEMPLATE = \ app/locale/NUT-Monitor.pot \ app/locale/fr/fr.po \ @@ -113,6 +117,17 @@ nutmonitordir = $(nut_with_nut_monitor_dir) nobase_nutmonitor_DATA = $(NUT_MONITOR_DISPATCHER_NOEXEC) $(NUT_MONITOR_COMMON) nobase_nutmonitor_SCRIPTS = $(NUT_MONITOR_DISPATCHER_SCRIPT) +if HAVE_MSGFMT +app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po + $(MSGFMT) -c "$<" -o "$@" + +app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po + $(MSGFMT) -c "$<" -o "$@" + +app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po + $(MSGFMT) -c "$<" -o "$@" +endif HAVE_MSGFMT + if WITH_NUT_MONITOR_PY2GTK2 nobase_nutmonitor_DATA += $(NUT_MONITOR_PY2GTK2) nobase_nutmonitor_SCRIPTS += $(NUT_MONITOR_PY2GTK2_GENERATED_SCRIPT) From 7ea574ec4f6d27134532c023407b19c48e62c8de Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 1 Jul 2023 01:28:33 +0200 Subject: [PATCH 0845/1232] scripts/python/app/locale/*/LC_MESSAGES/NUT-Monitor.mo: update binary translation files --- .../app/locale/fr/LC_MESSAGES/NUT-Monitor.mo | Bin 6505 -> 6264 bytes .../app/locale/it/LC_MESSAGES/NUT-Monitor.mo | Bin 6464 -> 6423 bytes .../app/locale/ru/LC_MESSAGES/NUT-Monitor.mo | Bin 9170 -> 9170 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo index bf2a9ab3f15b99e0b33225878da9bff30b04dadd..8053ece8eeea8aa0889bd24a4d27f16fddd6dd65 100644 GIT binary patch delta 1717 zcmXxkTS!z<6vpv2X=-_yoHBJX8@p$Y%}ka#Lr4V3Mqmf>cNMy%R>Ya`4B{f^#62P%sRh)&dk~S?6voquc2Ro_b?bJc@2SiJ9o&bnHd-_W+~#8s}n| z&i3J6oXPn1goXzCfO=w^Jl;Vb?&7oz=VK3+<6T^U!&rjpj7rlMp%*K#05{?dJb;>z zoAS}LVw{Sln9cZBLxV}%I!wVWxEQyiR-qd;(;n3C&Lbb|;u8x~H1aK>ACZ|v(Jd3*F7EZ*6NEK}$`TdLJ^^eKxUr;mrfvV_V zRE3I|ezl8<;s(x-vtE2wxE`#8&#Q$SdY(851P)# z&aSfp!Uc7d!*sQF^N{UeHK>7`kt*75?81XM z2R~vbPGodVC-QT@Kf&G-$qmumU40^8#>%4l4|g*b>R@d&Dfzfrr^%QObC z7BvGGz4DcLPy;OBz#Oaw_28ROdub;Ia1Uw;&!9HrIn+|euhY<4^rHrTlstcq+9YpK zuh)0vW1}2Yp*-rR5|(q&rdx~ZxDD&DGkJa=_4}u&2Y-j!wBM2O;`Wn<)@pS8f)(;> z&0sdF&x)|GEQ}zBUTE-ds=c=aN zL~18%NtTdWB84`mLa${dsS++HRVi(>I#QuE=8tr2jrH&iq@tPhll3|w=4yPEU7_^} zk}GsVtRYo;?P!%))mTMpU2Di0q(W6u)RNjW3LmMBxRfj*6d zdeyXsdKDE~FU4#!M6M;vNrg9YC~er4h-Iu#O$=sTb2%q+;y(Z8wyx-rXzZ}RG1A!< z_Jsn$rT$>RAFS|&Lg8frr`f$@LVHKzs{578iRCsp_i|4=5l>U%wx=r9`8>VMnUY`P hROd&tVqG1P*49Wzv^7@Z+{xdO$SBBmIi-cQ{{UMDon`<4 delta 1967 zcmajfUuaup7{~E9wXHQ<)1{qRH~;LUbF;Nga+22m$*ikQb^qHjHe@h|u?uTzY1;HG zRZueV#*4xRK_-qlL8^E$LBl2vFV+pFOvJ$$b}%Yc#2jXn4-uD~S>8dEesa}s01S7*#>jAILK#{f>^T6`Jr!IQ`j&3pJD zeuDM5hzbE6dM$wyHOyny@hC~m+X zF^Wyxgom5f=j5H{)V)T39z~zpcz$y2o^Aj>+nN#@EU4E+qhWs6R6)E zD{|Dr^SB#7MKxIiPt}FpsGU8Jt@s8i2 zq)p9eq1N4m1A705y@{j9$GpXXvYL-k-TXP~hF_s-x9EMpiF$xPQK_%xDYWAz&sJ>X zdq2`*Znmg``_ByAu~F~;qm^&SwQe>vr8?~(w76coO@ziHcW@g@rO~hm{S#BBR3@Iu z?VCOvAT($h_cd1IZ6lQBUheM>rADKNP~D#-wh|iJrD}Q~@f1O+-G90LsHWOXsFuoF zWkfjXCiJ!_Yn3rrIq@tiwL^qbr*uUL4b@0PHH{PMjV**~tDz>JWf=G z8go0LGV1lMBGe1&qfWy3ca=M9ulvHesTcFvLt~EBI@)F>?6_?Wr3=}E*5=&gXnLZM znJN40MymaL_gFh~lUXO1FF(C}-nVkhai)^7*zD|VbRsk3q@C!DQ~IO+$ksiPR6dh- zvbo8~P}<2P-8Ca|JCf+K5{YD@r`=B2wtv@1WOt^Jo%#25cDH+7ymTV4uY4=;rO#)T zF0L5lSQDIUN&WBhmW~Ct_^k3`u&?N;!ob}uDSVwyWOYw7&xmH1N z$OkQ$!E(%D6_zrqCXVrnV;2_U6TE`ssQzgT;u41Nz5jpRZ+}50_8ryl7uMr(*d;rH zQ$F-M#FU|*cCy6m8ZKi2?qehVz#9CIU06aI+V}vr;RyEN8?3~ySdD-1A)ff(AC#R} zAmtLY^W!DJoc8CF3&1zLmyC??4mYufH&}8)LRVPa$?@M cK)Z9>%LOVO^D2U#)4a77+zf3^7w;CH0ZAZRT>t<8 delta 906 zcmXZaO-PhM9LMqhQ@ifA>H1RUu2N|#wVL{{N?Un}mQHn&1v~0tB@je3MG<+3!b3p_ z5781tk#-QIxAiEp;wiC9CxeiLkWP!;Br^K`aABCwywCh+=6SM^{E%_Hw`O+xq*)Yy zBgw4X?3BO?Y{U?D;&Hr!?RXsnID{HEj2btMBzr(shEGfNXLyeK8?3_ha`UW~!dDu! z;V-PgzZl0#R@K4@G8a=A!FzZH$5G=SV-R0r7#B+Y%cc4TDzGioxNSU-I~AT;6NP^? zWE~>q8q(C~D$Sa46Hj0fFW><-U<1d$iYe5=N3jbZVK1&=9qwa2hO5o`u^H7qgLIki zQRt?yh@8Q;QIYRq0u`Qas0}so2CDxqYU44yh;ulJ@9;9V(m9NMsDrOz3+^Jx%1$4x z>(x`3qQS)^E@2OTM;EKvT{m$PbrVCVs~bhVL1MAjsQI5z ze`po28Sh`9pilD$xm`O(nEEs|sJD)z-n0d^a0lvUdQs!Es0b%ek>yYuFQX2)j+*xa zGgw4Dc{*lx*6y$X1xV$K^^EDDw3b5gA}n9V{!jQpwlt`bD-O~ raS=blrS^v=I3Z?V(;S diff --git a/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo index e5c3c6dfe3497a2339a532cd338efd5394b9381e..a924cefbf754454b3540b0c7f65eb03f703db4f6 100644 GIT binary patch delta 941 zcmXZbOGuSL6ae74rdHZRd)Y(N%wCG7wK96p3xyU@q4W@i3ThE8YEz52xhS#-7eZu^ zL{f`zVFb0SMMxC2=(dq4uw4a0K`o?$zJnM3JKvfAALh)QnVW0NwT+(1WFMxK?#@fe zllII{sg#GfkUgBs^PI_E&R`#7+)XxckcAv$jDN!zKh8OvU@<52{a;+EpD9b(R3@m= zEM^NMaT^!#7?<%ZW8!OU<}H@+6_+r_82^n${L5J^D4+gb%6MPPc)y;pftK=YN{a;B z@&gXCTK_Ot@d7I|Dc#{I{b#a7qH3#L%T0_4kFb`c=+c!jdnv6buC%~;q~HgT9^ z%;p3;1huxr z6|Hvx99=f`s(0+#J!c2U^Zh305fimDN_viwxIgbb#!eq| tHYXVWuJ8HpQ;a)Tvf3|#YC$*a+0MR!slpGLhJklQJ($q#;h5`jYU3MHl@_mqG6hw-B5C~8}+)NO_7U*txTa^ zpitsUO8H1qHf4$I(u&%}F65);_q4bE@A;kc|DVot&U2o3q-CV#(aB79D5W&GASF*~ zTA0#Y9^?{sa6Zp)HqUV;dl~aCv5x)B<4eZ;w~YCtoX0WF;?LZ8lI6x}QOf$IRH0eM z21ej!E@nGd@)Tp?9yahQ3;CMG9A?ZPXFmV3fSID{?}d!_RgCvFi~}?jWm8(Jvm-a5 zl@-Q^SjBFZW>Okpm+@0kB2c+quH$CLf`_@9oh;>fHu4rL`Gu|g$D=$TXg%*|b=K;9 zW*es%3%5zfz>Jj6G8QggF}S4m1+*iTP-rzzui-eJDg_VODQW3BYx#i@_z&A; zv{nJQx@^kIcbw!JZ9YB7jo(n6q%lU(O)&0klI@&g6jgiWbnSG~wWn^%a_VK&%ne43 z++%Fy1vl{rtHnDJ Date: Sat, 1 Jul 2023 01:31:54 +0200 Subject: [PATCH 0846/1232] scripts/python/app/locale/fr/*: set custom Project-Id-Version same as in other translations --- .../app/locale/fr/LC_MESSAGES/NUT-Monitor.mo | Bin 6264 -> 6260 bytes scripts/python/app/locale/fr/fr.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/fr/LC_MESSAGES/NUT-Monitor.mo index 8053ece8eeea8aa0889bd24a4d27f16fddd6dd65..9b7d3f958ceda992c2d22e59cf6bc4e60aa18318 100644 GIT binary patch delta 615 zcmXZZJxD@P6u|Lg_NA5eGPR^kG15MWH`I_q^f?se5EayBM9`8UB5kid8XBU;ph;Q^ zr=TH2XsyAap*;kLAS#5Y{{i7~f9KwJ?>+b2`(u8ZH#>FKq)lYXC6W-4!*-E2e8Lcx zunE60f`8bDkq(gMIfc0)7b_(gt+i`_Lrn1&i8hI;U2wBrVvxMdME5F8_~AgAcW zOVp>hMooNI>px--{b%Ggq>Ox0rO_KQxIVqXVVVHWqVAi-X*{U)Z&BwjJ`m{1U$GI( vs0lw%->O>cdzh^i1W>O$idyLe4&hQhSD$mVB-Yo0E2;gxOe&pEx_r)m2RJ~u delta 619 zcmXZZKS;ts6u|LkW~P*;W~P+cUkfE9S_;xctRyf|Xb5bohGuby;J36#LqpUUgj0bu z1_c#DYYh$!?I8#SQ6POE2tV%g?tXXo?%jRGequK}9mbMLB<>K&ipZf;q!(Xs6zgck zKMbR}Ph=P)xQH3-$0Lm387A=w2hi#g@n8^BIEMi&qZdzHVn~SKiUHP04SiV0A#9>< zu7w<+j$fdzyGPyk&0~n<2|gK^!UTWkaSx+- zj?-AfZfxQR{^A4%DB}SWs0EnVm0#jUO%SG`28p8{Jcnl7!WeEF1Qvp0XtA0l5s5dZ)H diff --git a/scripts/python/app/locale/fr/fr.po b/scripts/python/app/locale/fr/fr.po index 29a71a77f8..2eacbe8b2a 100644 --- a/scripts/python/app/locale/fr/fr.po +++ b/scripts/python/app/locale/fr/fr.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: NUT Monitor\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-10-14 22:47+0200\n" "PO-Revision-Date: 2013-10-14 22:50+0200\n" From 8b8ff7628c4b4d5c07050bff894c21045dd65759 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 12:09:34 +0200 Subject: [PATCH 0847/1232] scripts/python/Makefile.am: fix msgfmt call syntax for non-GNU makes --- scripts/python/Makefile.am | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index dfbedca182..37b883ff08 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -118,14 +118,15 @@ nobase_nutmonitor_DATA = $(NUT_MONITOR_DISPATCHER_NOEXEC) $(NUT_MONITOR_COMMON) nobase_nutmonitor_SCRIPTS = $(NUT_MONITOR_DISPATCHER_SCRIPT) if HAVE_MSGFMT +# Note lack of "$<" below - it is a non-portable GNU Make extension app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po - $(MSGFMT) -c "$<" -o "$@" + $(MSGFMT) -o "$@" "$^" app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po - $(MSGFMT) -c "$<" -o "$@" + $(MSGFMT) -o "$@" "$^" app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po - $(MSGFMT) -c "$<" -o "$@" + $(MSGFMT) -o "$@" "$^" endif HAVE_MSGFMT if WITH_NUT_MONITOR_PY2GTK2 From d3756e4826e4c2efd6e92cfb8e9737553254e184 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 15:00:51 +0200 Subject: [PATCH 0848/1232] docs/config-prereqs.txt: be sure to use pip3 for python3 examples --- docs/config-prereqs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 51f3b84c77..ebecf9f1ec 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -149,7 +149,7 @@ metadata about recently published package revisions: # To install the Python NUT-Monitor app, you may need some modules: # :; apt-get install pip # For Python3: -# :; pip install PyQt5 configparser +# :; python3 -m pip install PyQt5 configparser # For spell-checking, highly recommended if you would propose pull requests: :; apt-get install \ From 71c3565471f4ec4ab75f767d659f3886794838f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 16:43:20 +0200 Subject: [PATCH 0849/1232] scripts/python/Makefile.am: be sure target dirs for MSGFMT exist --- scripts/python/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 37b883ff08..6a98636d5b 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -120,12 +120,15 @@ nobase_nutmonitor_SCRIPTS = $(NUT_MONITOR_DISPATCHER_SCRIPT) if HAVE_MSGFMT # Note lack of "$<" below - it is a non-portable GNU Make extension app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po + @$(MKDIR_P) "$(builddir)/$(@D)" $(MSGFMT) -o "$@" "$^" app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po + @$(MKDIR_P) "$(builddir)/$(@D)" $(MSGFMT) -o "$@" "$^" app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po + @$(MKDIR_P) "$(builddir)/$(@D)" $(MSGFMT) -o "$@" "$^" endif HAVE_MSGFMT From d69658e840317d29da822af7ac7ad1f3c1fd674a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 16:44:01 +0200 Subject: [PATCH 0850/1232] scripts/python/Makefile.am: be sure target dirs for MSGFMT exist - regardless of ABS paths --- scripts/python/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 6a98636d5b..87d7f80777 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -120,15 +120,15 @@ nobase_nutmonitor_SCRIPTS = $(NUT_MONITOR_DISPATCHER_SCRIPT) if HAVE_MSGFMT # Note lack of "$<" below - it is a non-portable GNU Make extension app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po - @$(MKDIR_P) "$(builddir)/$(@D)" + @$(MKDIR_P) "$(builddir)/app/locale/fr/LC_MESSAGES" $(MSGFMT) -o "$@" "$^" app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po - @$(MKDIR_P) "$(builddir)/$(@D)" + @$(MKDIR_P) "$(builddir)/app/locale/it/LC_MESSAGES" $(MSGFMT) -o "$@" "$^" app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po - @$(MKDIR_P) "$(builddir)/$(@D)" + @$(MKDIR_P) "$(builddir)/app/locale/ru/LC_MESSAGES" $(MSGFMT) -o "$@" "$^" endif HAVE_MSGFMT From cc3e069a47a0a17a77d998d48d578c24e3cd2661 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 19:32:50 +0000 Subject: [PATCH 0851/1232] scripts/python/Makefile.am: avoid POT-Creation-Date in gettext translations --- scripts/python/Makefile.am | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 87d7f80777..30f92fbffc 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -119,17 +119,27 @@ nobase_nutmonitor_SCRIPTS = $(NUT_MONITOR_DISPATCHER_SCRIPT) if HAVE_MSGFMT # Note lack of "$<" below - it is a non-portable GNU Make extension +# The POT-Creation-Date: is removed by current python gettext builder to avoid +# "spurious" changes that do not benefit (otherwise unmodified) contents; see: +# https://github.com/sphinx-doc/sphinx/pull/3490 +# https://github.com/sphinx-doc/sphinx/issues/3443 app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po @$(MKDIR_P) "$(builddir)/app/locale/fr/LC_MESSAGES" - $(MSGFMT) -o "$@" "$^" + $(MSGFMT) -o "$@.tmp" "$^" + $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" + rm -f "$@.tmp" app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po @$(MKDIR_P) "$(builddir)/app/locale/it/LC_MESSAGES" - $(MSGFMT) -o "$@" "$^" + $(MSGFMT) -o "$@.tmp" "$^" + $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" + rm -f "$@.tmp" app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po @$(MKDIR_P) "$(builddir)/app/locale/ru/LC_MESSAGES" - $(MSGFMT) -o "$@" "$^" + $(MSGFMT) -o "$@.tmp" "$^" + $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" + rm -f "$@.tmp" endif HAVE_MSGFMT if WITH_NUT_MONITOR_PY2GTK2 From df0f5efcca9b87e60c8e00cdb1d340264cc93df4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 19:33:32 +0000 Subject: [PATCH 0852/1232] scripts/python/Makefile.am: refactor gettext translations --- scripts/python/Makefile.am | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 30f92fbffc..6efa707566 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -123,23 +123,23 @@ if HAVE_MSGFMT # "spurious" changes that do not benefit (otherwise unmodified) contents; see: # https://github.com/sphinx-doc/sphinx/pull/3490 # https://github.com/sphinx-doc/sphinx/issues/3443 +ACT_MSGFMT = { \ + $(MSGFMT) -o "$${OUTFILE}.tmp" "$${SRCFILE}" && \ + $(GREP) -v -E "^POT-Creation-Date: " < "$${OUTFILE}.tmp" > "$${OUTFILE}" && \ + rm -f "$${OUTFILE}.tmp" ; \ +} + app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po @$(MKDIR_P) "$(builddir)/app/locale/fr/LC_MESSAGES" - $(MSGFMT) -o "$@.tmp" "$^" - $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" - rm -f "$@.tmp" + SRCFILE="$^"; OUTFILE="$@"; $(ACT_MSGFMT) app/locale/it/LC_MESSAGES/NUT-Monitor.mo: app/locale/it/it.po @$(MKDIR_P) "$(builddir)/app/locale/it/LC_MESSAGES" - $(MSGFMT) -o "$@.tmp" "$^" - $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" - rm -f "$@.tmp" + SRCFILE="$^"; OUTFILE="$@"; $(ACT_MSGFMT) app/locale/ru/LC_MESSAGES/NUT-Monitor.mo: app/locale/ru/ru.po @$(MKDIR_P) "$(builddir)/app/locale/ru/LC_MESSAGES" - $(MSGFMT) -o "$@.tmp" "$^" - $(GREP) -v -E "^POT-Creation-Date: " < "$@.tmp" > "$@" - rm -f "$@.tmp" + SRCFILE="$^"; OUTFILE="$@"; $(ACT_MSGFMT) endif HAVE_MSGFMT if WITH_NUT_MONITOR_PY2GTK2 From 3317d5591237d35913912da4aec2779ed9d43840 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 2 Jul 2023 19:43:01 +0000 Subject: [PATCH 0853/1232] scripts/python/Makefile.am: refactor gettext translations to grep up source (text) file instead the output --- scripts/python/Makefile.am | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 6efa707566..328fe64742 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -123,10 +123,11 @@ if HAVE_MSGFMT # "spurious" changes that do not benefit (otherwise unmodified) contents; see: # https://github.com/sphinx-doc/sphinx/pull/3490 # https://github.com/sphinx-doc/sphinx/issues/3443 +# Note that OUTFILE may be in builddir (not necessarily same as srcdir) ACT_MSGFMT = { \ - $(MSGFMT) -o "$${OUTFILE}.tmp" "$${SRCFILE}" && \ - $(GREP) -v -E "^POT-Creation-Date: " < "$${OUTFILE}.tmp" > "$${OUTFILE}" && \ - rm -f "$${OUTFILE}.tmp" ; \ + $(GREP) -v -E '^.?POT-Creation-Date: ' < "$${SRCFILE}" > "$${OUTFILE}.tmpsrc" && \ + $(MSGFMT) -o "$${OUTFILE}" "$${OUTFILE}.tmpsrc" && \ + rm -f "$${OUTFILE}.tmpsrc" ; \ } app/locale/fr/LC_MESSAGES/NUT-Monitor.mo: app/locale/fr/fr.po From 3e9585f8b2a56320f256e94a6e6d2dc4cbd28807 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 3 Jul 2023 10:11:24 +0200 Subject: [PATCH 0854/1232] scripts/python/Makefile.am: no need to (re)define Makefile variable MSGFMT - already handled by autotools [#1977] --- scripts/python/Makefile.am | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 328fe64742..68a31489dd 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -24,10 +24,6 @@ PYTHON3_SITE_PACKAGES = @PYTHON3_SITE_PACKAGES@ BINDIR = @BINDIR@ -if HAVE_MSGFMT -MSGFMT = @MSGFMT@ -endif HAVE_MSGFMT - NUT_MONITOR_PY2GTK2 = \ app/ui/gui-1.3.glade \ app/nut-monitor-py2gtk2.desktop From dd49523dd9e2d22bd52ef9ddcf79fefd55c83376 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 3 Jul 2023 16:07:55 +0200 Subject: [PATCH 0855/1232] docs/download.txt: chunked-HTML chapter for "security.txt" moved due to daisychain years ago --- docs/download.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/download.txt b/docs/download.txt index b0de6e9c07..a605ef7dcb 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -12,7 +12,7 @@ You should always use PGP/GPG to verify the signatures before using any source c You can use the ifdef::website[] -link:docs/user-manual.chunked/ar01s09.html#verifySourceSig[following procedure] +link:docs/user-manual.chunked/ar01s10.html#verifySourceSig[following procedure] endif::website[] ifndef::website[] <>. From 91396d05b72e0b97bf8a1f6a71212d3161c6340d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 3 Jul 2023 16:08:54 +0200 Subject: [PATCH 0856/1232] docs/security.txt: fix ASCIIDOC markup [#1976] --- docs/security.txt | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/security.txt b/docs/security.txt index 6d54fb71df..51a50c5fcc 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -29,14 +29,17 @@ maintainer's signature keyring]: $ gpg --fetch-keys https://www.networkupstools.org/source/nut-key.gpg -NOTE: As of NUT 2.8.0, a new release key is used, but the `nut-key.gpg` should +[NOTE] +====== +As of NUT 2.8.0, a new release key is used, but the `nut-key.gpg` should be cumulative with older chain key files (includes them). You can view the key list in a downloaded copy of the URL above with: -+ + $ gpg --with-colons --import-options import-show --dry-run --import < nut-key.gpg -+ -and as of this writing, it should contain two key sets for various identities + +...and as of this writing, it should contain two key sets for various identities of "Arnaud Quette" and one set of "Jim Klimov". +====== Just in case, the previous key file used since NUT 2.7.3 release is stored as link:https://www.networkupstools.org/source/nut-key-2.7.3.gpg[NUT @@ -60,17 +63,21 @@ old maintainer's signature since 2002 until 2.7.3 release] Primary key fingerprint: B834 59F7 76B9 0224 988F 36C0 DE01 84DA 7043 DCF7 ... -NOTE: the previously used maintainer's signatures would output (with markup of +[NOTE] +====== +The previously used maintainer's signatures would output (with markup of older gpg tools here): -+ + gpg: Signature made Wed Apr 15 15:55:30 2015 CEST using RSA key ID 55CA5976 gpg: Good signature from "Arnaud Quette ..." ... -+ + or: + gpg: Signature made Thu Jul 5 16:15:05 2007 CEST using DSA key ID 204DDF1B gpg: Good signature from "Arnaud Quette ..." ... +====== //////// Maintainer notes for posterity: @@ -123,25 +130,25 @@ some examples follow: # Example original checksum to compare with, from NUT website: $ cat nut-2.8.0.tar.gz.sha256 c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 nut-2.8.0.tar.gz - + # Generate checksum of downloaded archive with perl (a NUT build dependency # generally, though you may have to install Digest::SHA module from CPAN): $ perl -MDigest::SHA=sha256_hex -le "print sha256_hex <>" nut-2.8.0.tar.gz c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 - + # Generate checksum of downloaded archive with openssl (another optional # NUT build dependency): $ openssl sha256 nut-2.8.0.tar.gz SHA256(nut-2.8.0.tar.gz)= c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 - + # Generate checksum of downloaded archive with coreutils: $ sha256sum nut-2.8.0.tar.gz c3e5a708da797b7c70b653d37b1206a000fcb503b85519fe4cdf6353f792bfe5 nut-2.8.0.tar.gz - + # Auto-check downloaded checksum against downloaded archive with coreutils: $ sha256sum -c nut-2.8.0.tar.gz.sha256 nut-2.8.0.tar.gz: OK - + # Generate checksum of downloaded archive with GPG: $ gpg --print-md SHA256 nut-2.8.0.tar.gz nut-2.8.0.tar.gz: C3E5A708 DA797B7C 70B653D3 7B1206A0 From cea3e64babb9c198d003b4be3c5517f44f4f48c3 Mon Sep 17 00:00:00 2001 From: Craig Holyoak Date: Fri, 7 Jul 2023 11:09:59 +1000 Subject: [PATCH 0857/1232] Added more variables from the CyberPower MIB --- drivers/cyberpower-mib.c | 44 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index cff6d64d88..9612a6bc01 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -24,7 +24,7 @@ #include "cyberpower-mib.h" -#define CYBERPOWER_MIB_VERSION "0.52" +#define CYBERPOWER_MIB_VERSION "0.53" #define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" /* CPS-MIB::ups */ @@ -70,6 +70,29 @@ static info_lkp_t cyberpower_battrepl_status[] = { { 0, NULL, NULL, NULL } }; +static info_lkp_t cyberpower_ups_status[] = { + { 1, "", NULL, NULL }, /* Normal */ + { 2, "OH", NULL, NULL }, /* Overheat */ + { 3, "HW", NULL, NULL }, /* Hardware Fault */ + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t cyberpower_transfer_reasons[] = { + { 1, "noTransfer", NULL, NULL }, + { 2, "highLineVoltage", NULL, NULL }, + { 3, "brownout", NULL, NULL }, + { 4, "selfTest", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t cyberpower_testdiag_results[] = { + { 1, "Ok", NULL, NULL }, + { 2, "Failed", NULL, NULL }, + { 3, "InvalidTest", NULL, NULL }, + { 4, "TestInProgress", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + /* Snmp2NUT lookup table for CyberPower MIB */ static snmp_info_t cyberpower_mib[] = { @@ -86,6 +109,8 @@ static snmp_info_t cyberpower_mib[] = { SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, CYBERPOWER_OID_MODEL_NAME, "CyberPower", SU_FLAG_STATIC, NULL }, + { "ups.id", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.3808.1.1.1.1.1.2.0", + "", SU_FLAG_OK | SU_FLAG_STATIC, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.3.0", "", SU_FLAG_STATIC, NULL }, @@ -102,9 +127,13 @@ static snmp_info_t cyberpower_mib[] = { SU_FLAG_OK | SU_STATUS_CAL, &cyberpower_cal_status[0] }, { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.2.5.0", "", SU_FLAG_OK | SU_STATUS_RB, &cyberpower_battrepl_status[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.10.1.0", "", + SU_FLAG_OK, &cyberpower_ups_status[0] }, { "ups.load", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.4.2.3.0", "", 0, NULL }, + { "ups.temperature", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.10.2.0", "", SU_FLAG_OK, NULL }, + /* Battery runtime is expressed in seconds */ { "battery.runtime", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "", 0, NULL }, @@ -128,11 +157,17 @@ static snmp_info_t cyberpower_mib[] = { 0, NULL }, { "battery.temperature", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.3.0", "", 0, NULL }, + /* upsBaseBatteryLastReplaceDate */ + { "battery.date", ST_FLAG_STRING, 8, ".1.3.6.1.4.1.3808.1.1.1.2.1.3.0", "", + SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL }, { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.1.0", "", 0, NULL }, { "input.frequency", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.4.0", "", 0, NULL }, + /* upsAdvanceInputLineFailCause */ + { "input.transfer.reason", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.3808.1.1.1.3.2.5.0", "", + SU_TYPE_INT | SU_FLAG_OK, &cyberpower_transfer_reasons[0] }, { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.1.0", "", 0, NULL }, @@ -171,6 +206,13 @@ static snmp_info_t cyberpower_mib[] = { { "calibrate.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, { "calibrate.stop", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceTestLastDiagnosticsDate */ + { "ups.test.date", ST_FLAG_STRING, 8, ".1.3.6.1.4.1.3808.1.1.1.7.2.4.0", "", + SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL }, + /* upsAdvanceTestDiagnosticsResults */ + { "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.7.2.3.0", "", + SU_FLAG_OK, &cyberpower_testdiag_results[0] }, + /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } } ; From 04cd93cdb9cbf55ecc7005ed63f979a55eca0bb4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 9 Jul 2023 18:19:01 +0200 Subject: [PATCH 0858/1232] Jenkinsfile-dynamatrix: try to ensure that stageName matches the dsbc contents [networkupstools/jenkins-dynamatrix#15] --- Jenkinsfile-dynamatrix | 60 ++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index 3102f96e8c..c44e565c52 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -240,12 +240,13 @@ import org.nut.dynamatrix.*; //dynacfgPipeline.buildSystem = 'ci_build.sh' //dynacfgPipeline.slowBuildDefaultBody = { echo "Running default custom build" } - dynacfgPipeline.slowBuildDefaultBody_autotools = { delegate -> setDelegate(delegate) + dynacfgPipeline.slowBuildDefaultBody_autotools = { def delegate -> setDelegate(delegate) + // Be sure to have a fixed resolved String here ASAP: + String stageNameClone = "${stageName}" def dsbcClone = dsbc.clone() - def stageNameClone = "${stageName}" stage('Investigate envvars (Autotools DEBUG)') { - echo "Running default custom build for '${stageName}' ==> ${dsbc.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true @@ -268,12 +269,13 @@ set | sort -n """ } } - dynacfgPipeline.slowBuildDefaultBody_ci_build = { delegate -> setDelegate(delegate) + dynacfgPipeline.slowBuildDefaultBody_ci_build = { def delegate -> setDelegate(delegate) + // Be sure to have a fixed resolved String here ASAP: + String stageNameClone = "${stageName}" def dsbcClone = dsbc.clone() - def stageNameClone = "${stageName}" stage('Investigate envvars (CI_Build DEBUG)') { - echo "Running default custom build for '${stageName}' ==> ${dsbc.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true @@ -321,7 +323,7 @@ set | sort -n """ //branchRegexTarget: dynacfgPipeline.branchStableRegex, branchRegexTarget: ~/fightwarn/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: dynacfgBase.commonLabelExpr, //defaultDynamatrixConfig: dynacfgBase.defaultDynamatrixConfig, @@ -359,7 +361,7 @@ set | sort -n """ branchRegexTarget: ~/fightwarn/, // NOTE: For fightwarn, we want some schenarios that would always build to test //appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: dynacfgBase.commonLabelExpr, //defaultDynamatrixConfig: dynacfgBase.defaultDynamatrixConfig, @@ -401,7 +403,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -438,7 +440,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: ["(NUT_BUILD_CAPS=valgrind=yes||NUT_BUILD_CAPS=valgrind)"], excludedNodelabels: ["NUT_BUILD_CAPS=valgrind=no"], @@ -483,7 +485,7 @@ set | sort -n """ //branchRegexTarget: dynacfgPipeline.branchStableRegex, branchRegexTarget: ~/fightwarn/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ dynamatrixAxesLabels: ['OS_FAMILY'], // + [ 'OS_DISTRO', 'MAKE'], requiredNodelabels: ["(NUT_BUILD_CAPS=cppcheck||NUT_BUILD_CAPS=cppcheck=yes)"], @@ -527,7 +529,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: "nut-builder:alldrv", requiredNodelabels: ["(NUT_BUILD_CAPS=drivers:all||nut-builder:alldrv)"], @@ -568,7 +570,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: "nut-builder:alldrv", requiredNodelabels: ["(NUT_BUILD_CAPS=drivers:all||nut-builder:alldrv)"], @@ -604,7 +606,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*)$/, branchRegexTarget: ~/fightwarn/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: "nut-builder:alldrv", requiredNodelabels: ["(NUT_BUILD_CAPS=drivers:all||nut-builder:alldrv)"], @@ -644,7 +646,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_PY, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: "nut-builder:alldrv", // TOTHINK: Should we also vary compilers here? @@ -684,7 +686,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_DOC, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: dynacfgBase.commonLabelExpr + " && doc-builder", //commonLabelExpr: infra.labelDocumentationWorker(), @@ -726,7 +728,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_TXT, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: dynacfgBase.commonLabelExpr + " && doc-builder", //commonLabelExpr: infra.labelDocumentationWorker(), @@ -764,7 +766,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -804,7 +806,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|.*fightwarn.*)$/, //branchRegexTarget: ~/fightwarn.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -838,7 +840,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*89.*)$/, branchRegexTarget: ~/fightwarn.*89.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -872,7 +874,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*|.*qemu.*)$/, //branchRegexTarget: ~/^(master|main|stable|.*qemu.*)$/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ //commonLabelExpr: "qemu-" + dynacfgBase.commonLabelExpr, commonLabelExpr: "qemu-nut-builder || ssh-qemu-nut-builder", @@ -914,7 +916,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*)$/, branchRegexTarget: ~/fightwarn/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -958,7 +960,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*89.*)$/, branchRegexTarget: ~/fightwarn.*89.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -995,7 +997,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|fightwarn.*)$/, //branchRegexTarget: dynacfgPipeline.branchStableRegex, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -1038,7 +1040,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*)$/, branchRegexTarget: ~/fightwarn/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -1078,7 +1080,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*)$/, branchRegexTarget: ~/fightwarn.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -1115,7 +1117,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*89.*)$/, branchRegexTarget: ~/fightwarn.*89.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -1152,7 +1154,7 @@ set | sort -n """ branchRegexSource: ~/^(PR-.+|.*fightwarn.*|.*Windows.*)$/, branchRegexTarget: ~/fightwarn|Windows-.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ requiredNodelabels: [], excludedNodelabels: [], @@ -1193,7 +1195,7 @@ set | sort -n """ //branchRegexSource: ~/^(PR-.+|.*fightwarn.*|.*Windows.*)$/, //branchRegexTarget: ~/fightwarn|Windows-.*/, appliesToChangedFilesRegex: dynacfgPipeline.appliesToChangedFilesRegex_C, - 'getParStages': { dynamatrix, Closure body -> + 'getParStages': { def dynamatrix, Closure body -> return dynamatrix.generateBuild([ commonLabelExpr: "cross-windows-nut-builder", dynamatrixAxesLabels: ['OS_FAMILY', 'OS_DISTRO', 'ARCH${ARCH_BITS}', 'COMPILER'], From 2c90a8897cb653d6c4e3aa33a3738fe9a2e15a1f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 18 Jul 2023 17:20:53 +0200 Subject: [PATCH 0859/1232] Introduce LICENSE-DCO into the source codebase [#1994] Signed-off-by: Jim Klimov --- LICENSE-DCO | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 LICENSE-DCO diff --git a/LICENSE-DCO b/LICENSE-DCO new file mode 100644 index 0000000000..49b8cb0549 --- /dev/null +++ b/LICENSE-DCO @@ -0,0 +1,34 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. From 4aaf2978e65599caf0b2a8ad5787ad701da08a9b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 18 Jul 2023 17:44:47 +0200 Subject: [PATCH 0860/1232] docs/developers.txt: add a chapter on DCO (Signed-Off-By) [#1994] Signed-off-by: Jim Klimov --- .github/pull_request_template.md | 5 ++++ docs/developers.txt | 41 ++++++++++++++++++++++++++++++-- docs/nut.dict | 4 +++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 288472971e..639fa20c8e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,6 +4,11 @@ as for which text documents to update. See also docs/developer-guide.txt for general points on NUT architecture and design. +* Please note that we require "Signed-Off-By" tags in each Git Commit + message, to conform to the common DCO (Developer Certificate of Origin) + as posted in LICENSE-DCO at root of NUT codebase as well as published + at https://developercertificate.org/ + * The checklist below is more of a reminder of steps to take and "dangers" to look out for. PRs to update this template are also welcome :) diff --git a/docs/developers.txt b/docs/developers.txt index b6e1984e59..5ff7db481e 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -1300,6 +1300,43 @@ You may notice that some older commits have `[[SVN:####]]` tags and Fossil-ID footers. These were lifted from the old SVN commit messages using reposurgeon, and should *not* be used as a guide for future commits. +Commit sign-off +--------------- + +Please also note that since 2023 we explicitly ask for contributions to be +"Signed Off" according to "Developer Certificate of Origin" as represented +in the `LICENSE-DCO` file in the root of NUT source tree (verbatim copy of +Version 1.1 of DCO published at https://developercertificate.org/ web site). +This is exactly the same one created and used by the Linux kernel developers. + +This is a developer's certification that he or she has the right to submit +the patch for inclusion into the project. Simply submitting a contribution +implies this agreement, however, please include a "Signed-off-by" tag in +every patch (this tag is a conventional way to confirm that you agree to +the DCO). In other words, this tag certifies that committer has the rights +to submit this work under the same license as the project and agrees to the +terms of a Developer Certificate of Origin. + +Note that while git commit hook tricks are available to automatically sign +off all commits, these signatures are intended to be a conscious (legally +meaningful) act -- hence they are not automated in git core with an easy +configuration option. + +For more details see: + +* https://github.com/networkupstools/nut/issues/1994 +* https://stackoverflow.com/questions/1962094/what-is-the-sign-off-feature-in-git-for +* https://stackoverflow.com/questions/15015894/git-add-signed-off-by-line-using-format-signoff-not-working + +You are also encouraged to set up a PGP key, make its public part known, and +use it to sign your git commits (in addition to the `Signed-Off-By` tag) by +also passing a `-S` option or calling `git config commit.gpgsign true` once. +Numerous public articles can walk you through this ordeal, including: + +* https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits +* https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key +* https://www.kernel.org/doc/html/v4.19/process/maintainer-pgp-guide.html + Repository etiquette and quality assurance ------------------------------------------ @@ -1350,11 +1387,11 @@ Here is an example workflow: # Hack away git add changed-file.c - git commit + git commit -s # Fix a typo in a file or commit message: - git commit -a --amend + git commit -s -a --amend # Someone committed something to the central repository. Fetch it. diff --git a/docs/nut.dict b/docs/nut.dict index 025c5be327..e8db621273 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3189 utf-8 +personal_ws-1.1 en 3191 utf-8 AAS ABI ACFAIL @@ -240,6 +240,7 @@ DATACABLE DATAPATH DCE DCF +DCO DDD DDDDD DDDDDD @@ -1999,6 +2000,7 @@ google goto gotos gpg +gpgsign gpio gpiochip graphviz From 069b87ae45f12e16d995ceffc563483aa7b93d74 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 12:53:17 +0200 Subject: [PATCH 0861/1232] Update COPYING about LICENSE-DCO file Follow-up to #1995 Signed-off-by: Jim Klimov --- COPYING | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/COPYING b/COPYING index 22de43ea47..94adc8c31f 100644 --- a/COPYING +++ b/COPYING @@ -28,3 +28,9 @@ To the best of our knowledge, conditions of the 2/3-clause BSD, MIT, curl and CC BY-SA licenses allow redistribution and reuse of the codebase in projects made available under GPL license terms, as long as attribution is provided. + + NUT contributors are encouraged to "sign off" their git commits as a conscious + act done under Developer's Certificate of Origin. See the copy of "LICENSE-DCO" + in the root of this distribution, but please note that it is not a "license" on + its own - rather a proclamation that work was done and submitted according to + applicable open-source licenses. From b55bf6c2fecf08536b0970fa19f83c89e99b0e1e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 15:02:35 +0200 Subject: [PATCH 0862/1232] nut.dict: bump for nut-website changes Signed-off-by: Jim Klimov --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index e8db621273..decec01875 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3191 utf-8 +personal_ws-1.1 en 3193 utf-8 AAS ABI ACFAIL @@ -2070,6 +2070,7 @@ idm ie ietf ifdef +ifeval ifndef ignoreFailures ignorelb @@ -3125,6 +3126,7 @@ wchar webNUT webnut webserver +websitelayout wf wget whitespace From 17255ed6d6596e80de660dbd7e448295c38460a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 15:52:47 +0200 Subject: [PATCH 0863/1232] nut.dict: bump for nut-website changes Signed-off-by: Jim Klimov --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index decec01875..c1647379d0 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3193 utf-8 +personal_ws-1.1 en 3195 utf-8 AAS ABI ACFAIL @@ -1613,6 +1613,7 @@ bsv bt bti btnG +btn btt buckboosthyst buckvolts @@ -2650,6 +2651,7 @@ rackmount raritan ratedva ratedwatts +raquo rb rcctl readline From 7552a122750e4a2e7e78bcb263376dbf864ac818 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 19:50:52 +0200 Subject: [PATCH 0864/1232] nut.dict: bump for nut-website changes 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 c1647379d0..21f5195b53 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3195 utf-8 +personal_ws-1.1 en 3196 utf-8 AAS ABI ACFAIL @@ -433,6 +433,7 @@ Gomes Goncalves Gordeev Gough +Grafana Grafenthal Gtec GuardEnd From 4c6cb84d4de1876f1e70837630ad845bd794c10f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 19:58:17 +0200 Subject: [PATCH 0865/1232] docs/user-manual.txt, docs/features.txt: bump manufacturer count --- docs/features.txt | 2 +- docs/user-manual.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 65dd6d85e8..6d34fd4c56 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -18,7 +18,7 @@ More and more appliances manufacturers are bundling NUT... Multiple manufacturer and device support ---------------------------------------- -- Monitors many UPS, PDU, ATS, PSU and SCD models from more than 140 +- Monitors many UPS, PDU, ATS, PSU and SCD models from more than 170 manufacturers with a unified interface (link:stable-hcl.html[Hardware Compatibility List]). diff --git a/docs/user-manual.txt b/docs/user-manual.txt index 638f113e87..4109b9629f 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -15,7 +15,7 @@ Units and Solar Controllers. NUT provides many control and monitoring <>, with a uniform control and management interface. -More than 140 different manufacturers, and several thousands of models are +More than 170 different manufacturers, and several thousands of models are <>. This software is the combined effort of many From 2ced48d1b7d9c97b1488d206fb619689081340ec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 30 Jul 2023 19:59:01 +0200 Subject: [PATCH 0866/1232] docs/features.txt: update notes about networked devices and about Windows builds --- docs/features.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 6d34fd4c56..502e7fc88b 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -26,7 +26,7 @@ manufacturers with a unified interface common interface: * serial, * USB, - * network (SNMP, Eaton / MGE XML/HTTP). + * network (SNMP, Eaton / MGE XML/HTTP, IPMI). Multiple architecture support ----------------------------- @@ -38,7 +38,7 @@ common set of tools, even crossing architectures. Apple's OS X, commercial Solaris and open-source illumos distros, IRIX, HP/UX, Tru64 Unix, and AIX. -- Windows users may be able to build it directly with Cygwin. +- Windows users may be able to build it directly with MSYS2, MinGW or Cygwin. There is also a port of the client-side monitoring to Windows called WinNUT. - Your system will probably run it too. You just need a good C compiler and From 8e7121041e0b90b057d47c783fc2c99034664ada Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 31 Jul 2023 13:35:48 +0200 Subject: [PATCH 0867/1232] drivers/cyberpower-mib.c, NEWS: extend support to devices which report the shorter Vendor OID as their sysOID [#1997] Closes: #1997 Signed-off-by: Jim Klimov --- NEWS | 2 ++ drivers/cyberpower-mib.c | 10 +++++++++- drivers/cyberpower-mib.h | 1 + drivers/snmp-ups.c | 3 ++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 11385cf61d..989e1bd8be 100644 --- a/NEWS +++ b/NEWS @@ -153,6 +153,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. driver [#1716] * `baytech-mib.c` subdriver: fixed `baytech_outlet_status_info[]` set of valid outlet status values [#1871] + * `cyberpower-mib.c` subdriver: support devices which report the shorter + Vendor OID as their sysOID, e.g. "CyberPower PowerPanel Personal" [#1997] - The `bestfortress` driver shutdown handling was fixed to use a non-trivial default timeout [#1820] diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index cff6d64d88..89574b8744 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -24,12 +24,17 @@ #include "cyberpower-mib.h" -#define CYBERPOWER_MIB_VERSION "0.52" +#define CYBERPOWER_MIB_VERSION "0.53" #define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" /* CPS-MIB::ups */ #define CYBERPOWER_SYSOID ".1.3.6.1.4.1.3808.1.1.1" +/* Per https://github.com/networkupstools/nut/issues/1997 + * some CPS devices offer the shorter vendor OID as sysOID + */ +#define CYBERPOWER_SYSOID2 ".1.3.6.1.4.1.3808" + /* https://www.cyberpowersystems.com/products/software/mib-files/ */ /* Per CPS MIB 2.9 upsBaseOutputStatus OBJECT-TYPE: */ static info_lkp_t cyberpower_power_status[] = { @@ -177,3 +182,6 @@ static snmp_info_t cyberpower_mib[] = { mib2nut_info_t cyberpower = { "cyberpower", CYBERPOWER_MIB_VERSION, NULL, CYBERPOWER_OID_MODEL_NAME, cyberpower_mib, CYBERPOWER_SYSOID, NULL }; + +mib2nut_info_t cyberpower2 = { "cyberpower", CYBERPOWER_MIB_VERSION, NULL, + CYBERPOWER_OID_MODEL_NAME, cyberpower_mib, CYBERPOWER_SYSOID2, NULL }; diff --git a/drivers/cyberpower-mib.h b/drivers/cyberpower-mib.h index 9db422250e..f8a44d24bd 100644 --- a/drivers/cyberpower-mib.h +++ b/drivers/cyberpower-mib.h @@ -5,5 +5,6 @@ #include "snmp-ups.h" extern mib2nut_info_t cyberpower; +extern mib2nut_info_t cyberpower2; #endif /* CYBERPOWER_MIB_H */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index a9073aaa62..558c72e61f 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -104,6 +104,7 @@ static mib2nut_info_t *mib2nut[] = { &bestpower, /* This struct comes from : bestpower-mib.c */ &compaq, /* This struct comes from : compaq-mib.c */ &cyberpower, /* This struct comes from : cyberpower-mib.c */ + &cyberpower2, /* This struct comes from : cyberpower-mib.c */ &delta_ups, /* This struct comes from : delta_ups-mib.c */ &eaton_ats16_nmc, /* This struct comes from : eaton-ats16-nmc-mib.c */ &eaton_ats16_nm2, /* This struct comes from : eaton-ats16-nm2-mib.c */ @@ -173,7 +174,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.29" +#define DRIVER_VERSION "1.30" /* driver description structure */ upsdrv_info_t upsdrv_info = { From 567d5010d0f14077a79f393e112db9a473711291 Mon Sep 17 00:00:00 2001 From: Tomasz Fortuna Date: Mon, 31 Jul 2023 22:20:59 +0200 Subject: [PATCH 0868/1232] drivers/nutdrv_qx.c: improve Armac subdriver Based on a debug output from a newer device (*/PF1) we've improved understanding on how: - those devices encode the length of a chunk of data. - how the end of transmission can be marked / detected. Changed: - Empty buffer before sending command to clear any residual data. - Detect end of message by end of line character \r (0x0d). - Refactor "6" into a READ_SIZE constant. - Limit bytes_available nibble to available READ_SIZE. Signed-off-by: Tomasz bla Fortuna --- NEWS | 2 ++ data/driver.list.in | 2 +- drivers/nutdrv_qx.c | 68 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 11385cf61d..8cf46b9413 100644 --- a/NEWS +++ b/NEWS @@ -99,6 +99,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - nutdrv_qx updates: * the `voltronic_qs_protocol` should now accept both "V" (as before) and newly "H" dialects, which otherwise seem interchangeable [#1623] + * the `armac` subdriver was enhanced to support devices with a different + response pattern than previously expected per initial contribution [#1978] - usbhid-ups updates: * cps-hid subdriver now applies same report descriptor fixing logic to diff --git a/data/driver.list.in b/data/driver.list.in index e175a6bc4d..f51801fc0b 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -115,7 +115,7 @@ "ARTronic" "ups" "2" "ARTon Platinium Combo 3.1 10/15/20 kVA" "USB" "blazer_usb" "ARTronic" "ups" "2" "ARTon Platinium RT 1/2/3/6/10 kVA" "USB" "blazer_usb" -"Armac" "ups" "2" "R/2000I/PSW" "(USB ID 0925:1234)" "nutdrv_qx" +"Armac" "ups" "2" "R/2000I/PSW and PF1 series" "(USB ID 0925:1234)" "nutdrv_qx" "ASEM SPA" "ups" "5" "PB1300 UPS" "i2c" "asem" diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 350c555a06..dcdda5010b 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1761,9 +1761,10 @@ static void *ablerex_subdriver_fun(USBDevice_t *device) */ static int armac_command(const char *cmd, char *buf, size_t buflen) { - char tmpbuf[6]; - int ret = 0; - size_t i, bufpos; + const int READ_SIZE = 6; + char tmpbuf[READ_SIZE]; + int ret = 0; + size_t i, bufpos; const size_t cmdlen = strlen(cmd); /* UPS ignores (doesn't echo back) unsupported commands which makes @@ -1788,6 +1789,17 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) } upsdebugx(4, "armac command %.*s", (int)strcspn(cmd, "\r"), cmd); + /* Cleanup buffer before sending a new command */ + for (i = 0; i < 10; i++) { + ret = usb_interrupt_read(udev, 0x81, + (usb_ctrl_charbuf)tmpbuf, READ_SIZE, 100); + if (ret != READ_SIZE) { + // Timeout - buffer is clean. + break; + } + upsdebugx(4, "armac cleanup ret i=%ld ret=%d ctrl=%02hhx", i, ret, tmpbuf[0]); + } + /* Send command to the UPS in 3-byte chunks. Most fit 1 chunk, except for eg. * parameterized tests. */ for (i = 0; i < cmdlen;) { @@ -1810,21 +1822,25 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) return ret; } + /* Wait for response to buffer */ + usleep(2000); memset(buf, 0, buflen); bufpos = 0; - while (bufpos + 6 < buflen) { + while (bufpos + READ_SIZE < buflen) { size_t bytes_available; /* Read data in 6-byte chunks */ - ret = usb_interrupt_read(udev, - 0x81, - (usb_ctrl_charbuf)tmpbuf, 6, 1000); + ret = usb_interrupt_read(udev, 0x81, + (usb_ctrl_charbuf)tmpbuf, READ_SIZE, 1000); /* Any errors here mean that we are unable to read a reply * (which will happen after successfully writing a command * to the UPS) */ - if (ret != 6) { + if (ret != READ_SIZE) { + /* NOTE: If end condition is invalid for particular UPS we might make one + * request more and get this error. If bufpos > (say) 10 this could be ignored + * and the reply correctly read. */ upsdebugx(1, "interrupt read error: %s (%d)", ret ? nut_usb_strerror(ret) : "timeout", @@ -1838,20 +1854,50 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) tmpbuf[0], tmpbuf[1], tmpbuf[2], tmpbuf[3], tmpbuf[4], tmpbuf[5], tmpbuf[1], tmpbuf[2], tmpbuf[3], tmpbuf[4], tmpbuf[5]); + /* + * On most tested devices (including R/2000I/PSW) this was equal to the number of + * bytes returned in the buffer, but on some newer UPS (R/3000I/PF1) it was 1 more + * (1 control + 5 bytes transferred and bytes_available equal to 6 instead of 5). + * + * Current assumption is that this is number of bytes available on the UPS side + * with up to 5 (ret - 1) transferred. + */ bytes_available = (unsigned char)tmpbuf[0] & 0x0f; if (bytes_available == 0) { /* End of transfer */ break; } - memcpy(buf + bufpos, tmpbuf + 1, bytes_available); - bufpos += bytes_available; + if (bytes_available > READ_SIZE - 1) { + /* Single interrupt transfer has 1 control + 5 data bytes */ + bytes_available = READ_SIZE - 1; + } + + /* Copy bytes into the final buffer while detecting end of line - \r */ + for (i = 0; i < bytes_available; i++) { + buf[bufpos++] = tmpbuf[i + 1]; + if (tmpbuf[i + 1] == 0x0d) { + if (i + 1 != bytes_available) { + upsdebugx(3, "trailing bytes in serial transmission found: %" PRIuSIZE " copied out of %" PRIuSIZE, + i + 1, bytes_available + ); + } + /* Break through two loops */ + goto end_of_message; + } + if (tmpbuf[i + 1] == 0x00) { + /* Happens when a manually turned off UPS is connected to the USB */ + upsdebugx(3, "null byte read - is UPS off?"); + return 0; + } + } if (bytes_available <= 2) { /* Slow down, let the UPS buffer more bytes */ - usleep(15000); + usleep(10000); } } +end_of_message: if (bufpos + 6 >= buflen) { upsdebugx(2, "Protocol error, too much data read."); From 621af62fd7af3fea996500656da41f7135470fde Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 2 Aug 2023 21:30:36 +0200 Subject: [PATCH 0869/1232] tools/nut-ddl-dump.sh: update scripting style (quotes, comments, etc) Signed-off-by: Jim Klimov --- tools/nut-ddl-dump.sh | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tools/nut-ddl-dump.sh b/tools/nut-ddl-dump.sh index d006b693c7..eaed8c8ba8 100755 --- a/tools/nut-ddl-dump.sh +++ b/tools/nut-ddl-dump.sh @@ -2,7 +2,9 @@ ################################################################################ # A script to ease the generation of NUT device dumps for NUT Devices Dumps Library ################################################################################ -# Author: (C) Arnaud Quette +# Authors: +# Copyright (C) 2015 - 2017 by Arnaud Quette +# Copyright (C) 2020 - 2023 by Jim Klimov # License: GPL v2+ ################################################################################ # FIXME: @@ -18,38 +20,38 @@ if [ -z "$1" ]; then echo "$strUsage" exit else - DDL_DEVICE_NAME=$1 + DDL_DEVICE_NAME="$1" fi # Test communication with the device -upscResult="`upsc ${DDL_DEVICE_NAME} 2> /dev/null`" +upscResult="`upsc "${DDL_DEVICE_NAME}" 2> /dev/null`" if [ $? -gt 0 ]; then - echo "Can't communicate with ${DDL_DEVICE_NAME}" + echo "Can't communicate with ${DDL_DEVICE_NAME}" >&2 exit fi # Collect more information dumpDate="`date -R`" -upsrwResult="`upsrw ${DDL_DEVICE_NAME} 2> /dev/null`" -upscmdResult="`upscmd -l ${DDL_DEVICE_NAME} 2> /dev/null`" +upsrwResult="`upsrw "${DDL_DEVICE_NAME}" 2> /dev/null`" +upscmdResult="`upscmd -l "${DDL_DEVICE_NAME}" 2> /dev/null`" # Build the filename # ________. # Process the Manufacturer name -RAW_DDL_MFR="`upsc ${DDL_DEVICE_NAME} device.mfr 2>/dev/null`" +RAW_DDL_MFR="`upsc "${DDL_DEVICE_NAME}" device.mfr 2>/dev/null`" if [ "${RAW_DDL_MFR}" = "EATON" ]; then RAW_DDL_MFR="Eaton" fi # Replace spaces with underscores -DDL_MFR="`echo ${RAW_DDL_MFR} | sed s/\ /_/g`" +DDL_MFR="`echo "${RAW_DDL_MFR}" | sed s/\ /_/g`" # Process the Model name # Replace spaces with underscores -RAW_DDL_MODEL="`upsc ${DDL_DEVICE_NAME} device.model 2>/dev/null`" -DDL_MODEL="`echo ${RAW_DDL_MODEL} | sed s/\ /_/g`" +RAW_DDL_MODEL="`upsc "${DDL_DEVICE_NAME}" device.model 2>/dev/null`" +DDL_MODEL="`echo "${RAW_DDL_MODEL}" | sed s/\ /_/g`" # Process the driver name and NUT version -DDL_DRIVER_NAME="`upsc ${DDL_DEVICE_NAME} driver.name 2>/dev/null`" -DDL_NUT_VERSION="`upsc ${DDL_DEVICE_NAME} driver.version 2>/dev/null`" -# TODO: check if a similar file exists, to update Report nb +DDL_DRIVER_NAME="`upsc "${DDL_DEVICE_NAME}" driver.name 2>/dev/null`" +DDL_NUT_VERSION="`upsc "${DDL_DEVICE_NAME}" driver.version 2>/dev/null`" +# TODO: check if a similar file exists in nut-ddl repo, to update Report nb DDL_REPORT_NUMBER="01" DDL_FILENAME="${DDL_MFR}__${DDL_MODEL}__${DDL_DRIVER_NAME}__${DDL_NUT_VERSION}__${DDL_REPORT_NUMBER}.dev" From 269ae608e6bbbde4785b6f5f4f9f4c44026a846b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 2 Aug 2023 21:31:23 +0200 Subject: [PATCH 0870/1232] tools/nut-ddl-dump.sh: generate the report with use of DEVICE:COMMENT: and DEVICE:COMMENT-BLOCK:FIXME:(UPSRW|UPSCMD): sections (and place them after upsc dump) Related-to: https://github.com/networkupstools/nut-ddl/issues/32 Signed-off-by: Jim Klimov --- tools/nut-ddl-dump.sh | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/nut-ddl-dump.sh b/tools/nut-ddl-dump.sh index eaed8c8ba8..4ddd1d857a 100755 --- a/tools/nut-ddl-dump.sh +++ b/tools/nut-ddl-dump.sh @@ -56,12 +56,22 @@ DDL_REPORT_NUMBER="01" DDL_FILENAME="${DDL_MFR}__${DDL_MODEL}__${DDL_DRIVER_NAME}__${DDL_NUT_VERSION}__${DDL_REPORT_NUMBER}.dev" # Dump device data into the file -echo "# Device dump generated by $0 on $dumpDate" > ${DDL_FILENAME} -echo "# upsrw output:" >> ${DDL_FILENAME} -echo "${upsrwResult}" | sed -e 's/^/# /' >> ${DDL_FILENAME} -echo "# upscmd output:" >> ${DDL_FILENAME} -echo "${upscmdResult}" | sed -e 's/^/# /' >> ${DDL_FILENAME} -echo "" >> ${DDL_FILENAME} -echo "# upsc output:" >> ${DDL_FILENAME} -echo "${upscResult}" >> ${DDL_FILENAME} -echo "${DDL_FILENAME} generated using ${DDL_DEVICE_NAME} " +( + echo "# DEVICE:COMMENT:" + echo "# Device dump generated by $0 on ${dumpDate}" + echo "# DEVICE:EOC" + echo "" + echo "# upsc output:" + echo "${upscResult}" + echo "" + echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSRW:" + echo "${upsrwResult}" | sed -e 's/^/# /' + echo "# DEVICE:EOC" + echo "" + echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSCMD:" + echo "${upscmdResult}" | sed -e 's/^/# /' + echo "# DEVICE:EOC" + echo "" +) > ${DDL_FILENAME} + +echo "${DDL_FILENAME} generated using ${DDL_DEVICE_NAME} on ${dumpDate}" From 8528a70b7e2b11823404bb3e4c3d34044f7d04b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 11:17:53 +0200 Subject: [PATCH 0871/1232] tools/nut-ddl-dump.sh: update generated markup Signed-off-by: Jim Klimov --- tools/nut-ddl-dump.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/nut-ddl-dump.sh b/tools/nut-ddl-dump.sh index 4ddd1d857a..0f2eefa0c7 100755 --- a/tools/nut-ddl-dump.sh +++ b/tools/nut-ddl-dump.sh @@ -61,15 +61,15 @@ DDL_FILENAME="${DDL_MFR}__${DDL_MODEL}__${DDL_DRIVER_NAME}__${DDL_NUT_VERSION}__ echo "# Device dump generated by $0 on ${dumpDate}" echo "# DEVICE:EOC" echo "" - echo "# upsc output:" + echo "# :; upsc ${DDL_DEVICE_NAME}" echo "${upscResult}" echo "" - echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSRW:" - echo "${upsrwResult}" | sed -e 's/^/# /' + echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSRW: ${DDL_DEVICE_NAME}" + echo "${upsrwResult}" | sed -e 's/^/# /' -e 's/^# $/#/' echo "# DEVICE:EOC" echo "" - echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSCMD:" - echo "${upscmdResult}" | sed -e 's/^/# /' + echo "# DEVICE:COMMENT-BLOCK:FIXME:UPSCMD: ${DDL_DEVICE_NAME}" + echo "${upscmdResult}" | sed -e 's/^/# /' -e 's/^# $/#/' echo "# DEVICE:EOC" echo "" ) > ${DDL_FILENAME} From 0cd533154b515abc8a7fedc9f67eff4f6b44fd96 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 11:18:12 +0200 Subject: [PATCH 0872/1232] tools/nut-ddl-dump.sh: suggest posting the file to nut-ddl repo Signed-off-by: Jim Klimov --- tools/nut-ddl-dump.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/nut-ddl-dump.sh b/tools/nut-ddl-dump.sh index 0f2eefa0c7..4a1a9f3958 100755 --- a/tools/nut-ddl-dump.sh +++ b/tools/nut-ddl-dump.sh @@ -57,6 +57,13 @@ DDL_FILENAME="${DDL_MFR}__${DDL_MODEL}__${DDL_DRIVER_NAME}__${DDL_NUT_VERSION}__ # Dump device data into the file ( + echo "# Please add if relevant: DEVICE:URL:REPORT: " + echo "# Please add if relevant: DEVICE:URL:VENDOR: " + echo "" + echo "# Please add comments for humans here and perhaps raise concerns about the data points," + echo "# see https://networkupstools.org/ddl/#devseq-files for comment-tag syntax" + echo "# strip sensitive data (passwords, SNMP community, serial number, IP address, host name...)" + echo "# and post as a pull request to https://github.com/networkupstools/nut-ddl/" echo "# DEVICE:COMMENT:" echo "# Device dump generated by $0 on ${dumpDate}" echo "# DEVICE:EOC" @@ -75,3 +82,4 @@ DDL_FILENAME="${DDL_MFR}__${DDL_MODEL}__${DDL_DRIVER_NAME}__${DDL_NUT_VERSION}__ ) > ${DDL_FILENAME} echo "${DDL_FILENAME} generated using ${DDL_DEVICE_NAME} on ${dumpDate}" +echo "Please revise and post as a pull request to https://github.com/networkupstools/nut-ddl/" From 7b0d582f40b8bea5c0e0584036a4508c801b6fc5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 20:11:58 +0200 Subject: [PATCH 0873/1232] drivers/apcupsd-ups.c: fix check for POLL_INTERVAL_MIN [#2007, #797 fallout] Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 47eea55d5c..838647bdbe 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -39,7 +39,7 @@ typedef unsigned long int nfds_t; #include "nut_stdint.h" #define DRIVER_NAME "apcupsd network client UPS driver" -#define DRIVER_VERSION "0.70" +#define DRIVER_VERSION "0.71" #define POLL_INTERVAL_MIN 10 @@ -331,7 +331,7 @@ void upsdrv_initinfo(void) if(getdata())fatalx(EXIT_FAILURE,"can't communicate with apcupsd!"); else dstate_dataok(); - poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; + poll_interval = (poll_interval < POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } void upsdrv_updateinfo(void) @@ -339,7 +339,7 @@ void upsdrv_updateinfo(void) if(getdata())upslogx(LOG_ERR,"can't communicate with apcupsd!"); else dstate_dataok(); - poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; + poll_interval = (poll_interval < POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } void upsdrv_shutdown(void) From 60cbba929281f0559680c0e336a2f4a3c999e20b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 20:13:07 +0200 Subject: [PATCH 0874/1232] NEWS: fix markup for "new devices" in 2.7.4 Signed-off-by: Jim Klimov --- NEWS | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index 989e1bd8be..34e8dfde14 100644 --- a/NEWS +++ b/NEWS @@ -788,22 +788,22 @@ Release notes for NUT 2.7.4 - what's new since 2.7.3: input, output, outlet and outlet.group) - support for new devices: - AEG PROTECT B / NAS - APC ATS AP7724 (should be supported) - Asium P700 - Eaton ATS - Eaton 5E 1100iUSB - Eaton E Series DX UPS 1-20 kVA - Eaton Powerware 9125-5000g - Electrys UPS 2500 - Fideltronic INIGO Viper 1200 - Legrand Keor Multiplug - LYONN CTB-800V - Micropower LCD 1000 - NHS Laser Senoidal 5000VA - Sweex model P220 - TS Shara - Various APCUPSD-controlled APC devices + * AEG PROTECT B / NAS + * APC ATS AP7724 (should be supported) + * Asium P700 + * Eaton ATS + * Eaton 5E 1100iUSB + * Eaton E Series DX UPS 1-20 kVA + * Eaton Powerware 9125-5000g + * Electrys UPS 2500 + * Fideltronic INIGO Viper 1200 + * Legrand Keor Multiplug + * LYONN CTB-800V + * Micropower LCD 1000 + * NHS Laser Senoidal 5000VA + * Sweex model P220 + * TS Shara + * Various APCUPSD-controlled APC devices - snmp-ups: * Improve automatic detection algorithm From 859b1d8ebb70c669c1cbe6a83291c20797f2ce97 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 20:14:22 +0200 Subject: [PATCH 0875/1232] NEWS: fix check for POLL_INTERVAL_MIN [#2007, #797 fallout] Signed-off-by: Jim Klimov --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 34e8dfde14..b5eff49184 100644 --- a/NEWS +++ b/NEWS @@ -615,6 +615,9 @@ refer to this change set (too long in the making) as NUT 2.7.5. - the powerpanel driver now also supports CyberPower OR1500LCDRTXL2U with serial cable [PR #538] + - apcupsd-ups: + * improvement for `POLL_INTERVAL_MIN` from PR #797 was buggy [#2007] + - powercom driver: implement `nobt` config parameter to skip battery check on initialization/startup [PR #1256] From d75adb5645adffbeb7192791e345532b24f7bd3b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 21:30:13 +0200 Subject: [PATCH 0876/1232] common/common.c: clarify "nsec" as "numsec" (not "nanosec") in difftimeval() Signed-off-by: Jim Klimov --- common/common.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common/common.c b/common/common.c index 391b993751..5861152713 100644 --- a/common/common.c +++ b/common/common.c @@ -667,17 +667,19 @@ double difftimeval(struct timeval x, struct timeval y) struct timeval result; double d; + /* Code below assumes that tv_sec is signed (time_t), + * but tv_usec is not necessarily */ /* Perform the carry for the later subtraction by updating y. */ if (x.tv_usec < y.tv_usec) { - intmax_t nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; - y.tv_usec -= 1000000 * nsec; - y.tv_sec += nsec; + intmax_t numsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; + y.tv_usec -= 1000000 * numsec; + y.tv_sec += numsec; } if (x.tv_usec - y.tv_usec > 1000000) { - intmax_t nsec = (x.tv_usec - y.tv_usec) / 1000000; - y.tv_usec += 1000000 * nsec; - y.tv_sec -= nsec; + intmax_t numsec = (x.tv_usec - y.tv_usec) / 1000000; + y.tv_usec += 1000000 * numsec; + y.tv_sec -= numsec; } /* Compute the time remaining to wait. From c52a97116fb7c4a658f3e62e5ac99646ac4225e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 21:31:01 +0200 Subject: [PATCH 0877/1232] common/common.c, include/common.h: introduce difftimespec() for completeness Signed-off-by: Jim Klimov --- common/common.c | 29 +++++++++++++++++++++++++++++ include/common.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/common/common.c b/common/common.c index 5861152713..f1bc020310 100644 --- a/common/common.c +++ b/common/common.c @@ -735,6 +735,35 @@ static nsec_t timespec_load_nsec(const struct timespec *ts) { return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; } + +double difftimespec(struct timespec x, struct timespec y) +{ + struct timespec result; + double d; + + /* Code below assumes that tv_sec is signed (time_t), + * but tv_nsec is not necessarily */ + /* Perform the carry for the later subtraction by updating y. */ + if (x.tv_nsec < y.tv_nsec) { + intmax_t numsec = (y.tv_nsec - x.tv_nsec) / 1000000000L + 1; + y.tv_nsec -= 1000000000L * numsec; + y.tv_sec += numsec; + } + + if (x.tv_nsec - y.tv_nsec > 1000000) { + intmax_t numsec = (x.tv_nsec - y.tv_nsec) / 1000000000L; + y.tv_nsec += 1000000000L * numsec; + y.tv_sec -= numsec; + } + + /* Compute the time remaining to wait. + * tv_nsec is certainly positive. */ + result.tv_sec = x.tv_sec - y.tv_sec; + result.tv_nsec = x.tv_nsec - y.tv_nsec; + + d = 0.000000001 * result.tv_nsec + result.tv_sec; + return d; +} #endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ /* Send (daemon) state-change notifications to an diff --git a/include/common.h b/include/common.h index 27524f3acc..3d0052f8fd 100644 --- a/include/common.h +++ b/include/common.h @@ -409,6 +409,9 @@ char * getfullpath(char * relative_path); /* Return a difference of two timevals as a floating-point number */ double difftimeval(struct timeval x, struct timeval y); +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC +double difftimespec(struct timespec x, struct timespec y); +#endif #ifndef HAVE_USLEEP /* int __cdecl usleep(unsigned int useconds); */ From bc0c41d2b00c7153b35cf04f70c2e5393d916fda Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 21:39:06 +0200 Subject: [PATCH 0878/1232] common/state.c, include/state.h: introduce st_tree_timespec_t and state_get_timestamp() and st_tree_node_compare_timestamp() to track age of state entries Signed-off-by: Jim Klimov --- common/state.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++-- include/state.h | 14 +++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/common/state.c b/common/state.c index 519e7a1ff7..ad6844746d 100644 --- a/common/state.c +++ b/common/state.c @@ -35,6 +35,8 @@ #include "state.h" #include "parseconf.h" +/* internal helpers */ + static void val_escape(st_tree_t *node) { char etmp[ST_MAX_VALUE_LEN]; @@ -128,6 +130,60 @@ static void st_tree_node_add(st_tree_t **nptr, st_tree_t *sptr) *nptr = sptr; } +static int st_tree_node_refresh_timestamp(const st_tree_t *node) +{ + if (!node) + return -1; + + return state_get_timestamp((st_tree_timespec_t *)&node->lastset); +} + +/* interface */ + +/* As underlying system methods: + * return 0 on success, -1 and errno on error + */ +int state_get_timestamp(st_tree_timespec_t *now) +{ + if (!now) + return -1; + +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC + return clock_gettime(CLOCK_MONOTONIC, now); +#else + return gettimeofday(now, NULL); +#endif +} + +/* Returns -1 if the node->lastset is "older" than cutoff, + * 0 if it is equal, or +1 if it is newer. + * Returns -2 or -3 if node or cutoff are null. + */ +int st_tree_node_compare_timestamp( + const st_tree_t *node, + const st_tree_timespec_t *cutoff +) { + double d; + + if (!node) + return -2; + + if (!cutoff) + return -3; + +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC + d = difftimespec(node->lastset, *cutoff); +#else + d = difftimeval(node->lastset, *cutoff); +#endif + + if (d < 0) + return -1; + if (d > 0) + return 1; + return 0; +} + /* remove a variable from a tree * except for variables with ST_FLAG_IMMUTABLE * (for override.* to survive) per issue #737 @@ -167,8 +223,6 @@ int state_delinfo(st_tree_t **nptr, const char *var) return 0; /* not found */ } -/* interface */ - int state_setinfo(st_tree_t **nptr, const char *var, const char *val) { while (*nptr) { @@ -185,6 +239,9 @@ int state_setinfo(st_tree_t **nptr, const char *var, const char *val) continue; } + /* refresh even if "skip-writing" same info value */ + st_tree_node_refresh_timestamp(node); + /* updating an existing entry */ if (!strcasecmp(node->raw, val)) { return 0; /* no change */ @@ -261,6 +318,7 @@ int state_addenum(st_tree_t *root, const char *var, const char *val) /* smooth over any oddities in the enum value */ pconf_encode(val, enc, sizeof(enc)); + st_tree_node_refresh_timestamp(sttmp); return st_tree_enum_add(&sttmp->enum_list, enc); } @@ -309,6 +367,7 @@ int state_addrange(st_tree_t *root, const char *var, const int min, const int ma return 0; /* failed */ } + st_tree_node_refresh_timestamp(sttmp); return st_tree_range_add(&sttmp->range_list, min, max); } @@ -326,6 +385,7 @@ int state_setaux(st_tree_t *root, const char *var, const char *auxs) return -1; /* failed */ } + st_tree_node_refresh_timestamp(sttmp); aux = strtol(auxs, (char **) NULL, 10); /* silently ignore matches */ @@ -422,6 +482,7 @@ void state_setflags(st_tree_t *root, const char *var, size_t numflags, char **fl return; } + st_tree_node_refresh_timestamp(sttmp); sttmp->flags = 0; for (i = 0; i < numflags; i++) { @@ -562,6 +623,7 @@ int state_delenum(st_tree_t *root, const char *var, const char *val) return 0; } + st_tree_node_refresh_timestamp(sttmp); return st_tree_del_enum(&sttmp->enum_list, val); } @@ -599,6 +661,7 @@ int state_delrange(st_tree_t *root, const char *var, const int min, const int ma return 0; } + st_tree_node_refresh_timestamp(sttmp); return st_tree_del_range(&sttmp->range_list, min, max); } diff --git a/include/state.h b/include/state.h index 97249a2726..ab37e203d9 100644 --- a/include/state.h +++ b/include/state.h @@ -32,6 +32,12 @@ extern "C" { #define ST_SOCK_BUF_LEN 512 +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC +typedef struct timespec st_tree_timespec_t; +#else +typedef struct timeval st_tree_timespec_t; +#endif + typedef struct st_tree_s { char *var; char *val; /* points to raw or safe */ @@ -45,6 +51,12 @@ typedef struct st_tree_s { int flags; long aux; + /* When was this entry last written (meaning that + * val/raw/safe, flags, aux, enum or range value + * was added, changed or deleted)? + */ + st_tree_timespec_t lastset; + struct enum_s *enum_list; struct range_s *range_list; @@ -52,6 +64,8 @@ typedef struct st_tree_s { struct st_tree_s *right; } st_tree_t; +int state_get_timestamp(st_tree_timespec_t *now); +int st_tree_node_compare_timestamp(const st_tree_t *node, const st_tree_timespec_t *cutoff); int state_setinfo(st_tree_t **nptr, const char *var, const char *val); int state_addenum(st_tree_t *root, const char *var, const char *val); int state_addrange(st_tree_t *root, const char *var, const int min, const int max); From bd91d3245ace3ae97969ff3af5ed6e4730e77c81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 21:52:31 +0200 Subject: [PATCH 0879/1232] common/state.c, include/state.h: introduce state_delinfo_olderthan() Signed-off-by: Jim Klimov --- common/state.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/state.h | 1 + 2 files changed, 41 insertions(+) diff --git a/common/state.c b/common/state.c index ad6844746d..9c78679cf7 100644 --- a/common/state.c +++ b/common/state.c @@ -223,6 +223,46 @@ int state_delinfo(st_tree_t **nptr, const char *var) return 0; /* not found */ } +int state_delinfo_olderthan(st_tree_t **nptr, const char *var, const st_tree_timespec_t *cutoff) +{ + while (*nptr) { + + st_tree_t *node = *nptr; + + if (strcasecmp(node->var, var) > 0) { + nptr = &node->left; + continue; + } + + if (strcasecmp(node->var, var) < 0) { + nptr = &node->right; + continue; + } + + if (node->flags & ST_FLAG_IMMUTABLE) { + upsdebugx(6, "%s: not deleting immutable variable [%s]", __func__, var); + return 0; + } + + if (st_tree_node_compare_timestamp(node, cutoff) >= 0) { + upsdebugx(6, "%s: not deleting recently updated variable [%s]", __func__, var); + return 0; + } + + /* whatever is on the left, hang it off current right */ + st_tree_node_add(&node->right, node->left); + + /* now point the parent at the old right child */ + *nptr = node->right; + + st_tree_node_free(node); + + return 1; + } + + return 0; /* not found */ +} + int state_setinfo(st_tree_t **nptr, const char *var, const char *val) { while (*nptr) { diff --git a/include/state.h b/include/state.h index ab37e203d9..60dc3433fe 100644 --- a/include/state.h +++ b/include/state.h @@ -81,6 +81,7 @@ void state_infofree(st_tree_t *node); void state_cmdfree(cmdlist_t *list); int state_delcmd(cmdlist_t **list, const char *cmd); int state_delinfo(st_tree_t **root, const char *var); +int state_delinfo_olderthan(st_tree_t **root, const char *var, const st_tree_timespec_t *cutoff); int state_delenum(st_tree_t *root, const char *var, const char *val); int state_delrange(st_tree_t *root, const char *var, const int min, const int max); st_tree_t *state_tree_find(st_tree_t *node, const char *var); From da13226eabb31a38e8941a8ca1276ae4efd554f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 22:18:40 +0200 Subject: [PATCH 0880/1232] drivers/apcupsd-ups.c: refactor getdata() return code paths [#2007] Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 76 ++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 838647bdbe..3f7e03c8bd 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -174,6 +174,7 @@ static int getdata(void) char *data; struct pollfd p; char bfr[1024]; + int ret = -1; #ifndef WIN32 int fd_flags; #else @@ -192,14 +193,18 @@ static int getdata(void) if (INVALID_FD_SOCK( p.fd = socket(AF_INET, SOCK_STREAM, 0) )) { upsdebugx(1,"socket error"); - return -1; + /* return -1; */ + ret = -1; + goto getdata_return; } if(connect(p.fd,(struct sockaddr *)&host,sizeof(host))) { upsdebugx(1,"can't connect to apcupsd"); - close(p.fd); - return -1; + /* close(p.fd); + return -1; */ + ret = -1; + goto getdata_return; } #ifndef WIN32 @@ -207,15 +212,19 @@ static int getdata(void) fd_flags = fcntl(p.fd, F_GETFL); if (fd_flags == -1) { upsdebugx(1,"unexpected fcntl(fd, F_GETFL) failure"); - close(p.fd); - return -1; + /* close(p.fd); + return -1; */ + ret = -1; + goto getdata_return; } fd_flags |= O_NONBLOCK; if(fcntl(p.fd, F_SETFL, fd_flags) == -1) { upsdebugx(1,"unexpected fcntl(fd, F_SETFL, fd_flags|O_NONBLOCK) failure"); - close(p.fd); - return -1; + /* close(p.fd); + return -1; */ + ret = -1; + goto getdata_return; } #else event = CreateEvent( @@ -244,20 +253,14 @@ static int getdata(void) if(read(p.fd,&n,2)!=2) { upsdebugx(1,"apcupsd communication error"); - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return -1; + ret = -1; + goto getdata_return; } if(!(x=ntohs(n))) { - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return 0; + ret = 0; + goto getdata_return; } else if(x<0||x>=(int)sizeof(bfr)) /* Note: LGTM.com suggests "Comparison is always false because x >= 0" @@ -268,11 +271,8 @@ static int getdata(void) */ { upsdebugx(1,"apcupsd communication error"); - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return -1; + ret = -1; + goto getdata_return; } #ifndef WIN32 @@ -284,11 +284,8 @@ static int getdata(void) if(read(p.fd,bfr,(size_t)x)!=x) { upsdebugx(1,"apcupsd communication error"); - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return -1; + ret = -1; + goto getdata_return; } bfr[x]=0; @@ -296,21 +293,15 @@ static int getdata(void) if(!(item=strtok(bfr," \t:\r\n"))) { upsdebugx(1,"apcupsd communication error"); - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return -1; + ret = -1; + goto getdata_return; } if(!(data=strtok(NULL,"\r\n"))) { upsdebugx(1,"apcupsd communication error"); - close(p.fd); -#ifdef WIN32 - CloseHandle(event); -#endif - return -1; + ret = -1; + goto getdata_return; } while(*data==' '||*data=='\t'||*data==':')data++; @@ -318,11 +309,16 @@ static int getdata(void) } upsdebugx(1,"unexpected connection close by apcupsd"); - close(p.fd); + ret = -1; + +getdata_return: + if (VALID_FD_SOCK(p.fd)) + close(p.fd); #ifdef WIN32 - CloseHandle(event); + if (event != NULL) + CloseHandle(event); #endif - return -1; + return ret; } void upsdrv_initinfo(void) From 8da3e8dc536cd9aca95faa8538dadeb2b772ac82 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 22:22:44 +0200 Subject: [PATCH 0881/1232] drivers/dstate.{c,h}: introduce dstate_delinfo_olderthan() Signed-off-by: Jim Klimov --- drivers/dstate.c | 14 ++++++++++++++ drivers/dstate.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/dstate.c b/drivers/dstate.c index a6b1b0e2fb..80435f08c0 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -1400,6 +1400,20 @@ int dstate_delinfo(const char *var) return ret; } +int dstate_delinfo_olderthan(const char *var, const st_tree_timespec_t *cutoff) +{ + int ret; + + ret = state_delinfo_olderthan(&dtree_root, var, cutoff); + + /* update listeners */ + if (ret == 1) { + send_to_all("DELINFO %s\n", var); + } + + return ret; +} + int dstate_delenum(const char *var, const char *val) { int ret; diff --git a/drivers/dstate.h b/drivers/dstate.h index ec26056cf5..2fa754defa 100644 --- a/drivers/dstate.h +++ b/drivers/dstate.h @@ -75,6 +75,7 @@ void dstate_delflags(const char *var, const int delflags); void dstate_setaux(const char *var, long aux); const char *dstate_getinfo(const char *var); void dstate_addcmd(const char *cmdname); +int dstate_delinfo_olderthan(const char *var, const st_tree_timespec_t *cutoff); int dstate_delinfo(const char *var); int dstate_delenum(const char *var, const char *val); int dstate_delrange(const char *var, const int min, const int max); From 92c7a956bab2b0a627476c1752d4b39ad4a2db1f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 22:23:31 +0200 Subject: [PATCH 0882/1232] drivers/apcupsd-ups.c: use dstate_delinfo_olderthan() to clean up obsoleted readings AFTER refreshing data from apcupsd daemon [#2007] Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 3f7e03c8bd..1751bf0daf 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -174,6 +174,7 @@ static int getdata(void) char *data; struct pollfd p; char bfr[1024]; + st_tree_timespec_t start; int ret = -1; #ifndef WIN32 int fd_flags; @@ -186,9 +187,7 @@ static int getdata(void) HANDLE event = NULL; #endif - for(x=0;nut_data[x].info_type;x++) - if(!(nut_data[x].drv_flags & DU_FLAG_INIT) && !(nut_data[x].drv_flags & DU_FLAG_PRESERVE)) - dstate_delinfo(nut_data[x].info_type); + state_get_timestamp((st_tree_timespec_t *)&start); if (INVALID_FD_SOCK( p.fd = socket(AF_INET, SOCK_STREAM, 0) )) { @@ -318,6 +317,12 @@ static int getdata(void) if (event != NULL) CloseHandle(event); #endif + + /* Remove any unprotected entries not refreshed in this run */ + for(x=0;nut_data[x].info_type;x++) + if(!(nut_data[x].drv_flags & DU_FLAG_INIT) && !(nut_data[x].drv_flags & DU_FLAG_PRESERVE)) + dstate_delinfo_olderthan(nut_data[x].info_type, &start); + return ret; } From 078123cfa157174973078a557318ed7488d8e470 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 22:26:49 +0200 Subject: [PATCH 0883/1232] NEWS: use dstate_delinfo_olderthan() to clean up obsoleted readings AFTER refreshing data from apcupsd daemon [#2007] Signed-off-by: Jim Klimov --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index b5eff49184..031b826ee6 100644 --- a/NEWS +++ b/NEWS @@ -617,6 +617,8 @@ refer to this change set (too long in the making) as NUT 2.7.5. - apcupsd-ups: * improvement for `POLL_INTERVAL_MIN` from PR #797 was buggy [#2007] + * fix to clean obsoleted readings (if any) AFTER getting new info from an + `apcupsd` daemon, to avoid the gap when NUT driver knows nothing [#2007] - powercom driver: implement `nobt` config parameter to skip battery check on initialization/startup [PR #1256] From c468f865e4b71badb44ce29cf031800b9cdb3778 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 22:32:58 +0200 Subject: [PATCH 0884/1232] common/state.c: initialize "lastset" in "state_setinfo()" when adding a new value Signed-off-by: Jim Klimov --- common/state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/state.c b/common/state.c index 9c78679cf7..793a1c6f1b 100644 --- a/common/state.c +++ b/common/state.c @@ -311,6 +311,7 @@ int state_setinfo(st_tree_t **nptr, const char *var, const char *val) (*nptr)->var = xstrdup(var); (*nptr)->raw = xstrdup(val); (*nptr)->rawsize = strlen(val) + 1; + st_tree_node_refresh_timestamp(*nptr); val_escape(*nptr); From 87e94fafea9fa5499876e7cae80acd6d846b1a23 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2023 18:43:20 +0200 Subject: [PATCH 0885/1232] Update drivers/nutdrv_qx.c Fix debug printout Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index dcdda5010b..eb2d3badde 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1797,7 +1797,7 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) // Timeout - buffer is clean. break; } - upsdebugx(4, "armac cleanup ret i=%ld ret=%d ctrl=%02hhx", i, ret, tmpbuf[0]); + upsdebugx(4, "armac cleanup ret i=%" PRIuSIZE " ret=%d ctrl=%02hhx", i, ret, tmpbuf[0]); } /* Send command to the UPS in 3-byte chunks. Most fit 1 chunk, except for eg. From 6547c613f7dcbfd7364d04f189b61aaccf5eb7a2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 09:38:21 +0200 Subject: [PATCH 0886/1232] drivers/nutdrv_qx.c: cast signed/unsigned int comparison Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index eb2d3badde..5c13460461 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1868,7 +1868,7 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) break; } - if (bytes_available > READ_SIZE - 1) { + if (bytes_available > (size_t)(READ_SIZE - 1)) { /* Single interrupt transfer has 1 control + 5 data bytes */ bytes_available = READ_SIZE - 1; } From 7b77e438dfe540350e52a34b3cec9da53565208f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 10:46:20 +0200 Subject: [PATCH 0887/1232] common/common.c: fix build scope for calls to timespec_load() and use of got_monoclock in upsnotify() [#1777 follow-up] 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 f1bc020310..0864f28b23 100644 --- a/common/common.c +++ b/common/common.c @@ -710,6 +710,8 @@ typedef uint64_t nsec_t; #define NSEC_PER_MSEC ((nsec_t) 1000000ULL) #define NSEC_PER_USEC ((nsec_t) 1000ULL) +# if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) && defined(HAVE_SD_NOTIFY) && (HAVE_SD_NOTIFY) +/* Limited to upsnotify() use-cases below, currently */ static usec_t timespec_load(const struct timespec *ts) { assert(ts); @@ -724,6 +726,8 @@ static usec_t timespec_load(const struct timespec *ts) { (usec_t) ts->tv_nsec / NSEC_PER_USEC; } +/* Not used, currently -- maybe later */ +/* static nsec_t timespec_load_nsec(const struct timespec *ts) { assert(ts); @@ -735,6 +739,8 @@ static nsec_t timespec_load_nsec(const struct timespec *ts) { return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; } +*/ +# endif /* WITH_LIBSYSTEMD && HAVE_SD_NOTIFY && !WITHOUT_LIBSYSTEMD */ double difftimespec(struct timespec x, struct timespec y) { @@ -777,14 +783,18 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) char msgbuf[LARGEBUF]; size_t msglen = 0; -#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC +#if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) && !(defined(WITHOUT_LIBSYSTEMD) && (WITHOUT_LIBSYSTEMD)) +# ifdef HAVE_SD_NOTIFY +# if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC /* In current systemd, this is only used for RELOADING/READY after * a reload action for Type=notify-reload; for more details see * https://github.com/systemd/systemd/blob/main/src/core/service.c#L2618 */ struct timespec monoclock_ts; int got_monoclock = clock_gettime(CLOCK_MONOTONIC, &monoclock_ts); -#endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ +# endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ +# endif /* HAVE_SD_NOTIFY */ +#endif /* WITH_LIBSYSTEMD */ /* Prepare the message (if any) as a string */ msgbuf[0] = '\0'; From d4b01c439a38c78fdf02b50103a9c2af45b374c7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 10:47:38 +0200 Subject: [PATCH 0888/1232] configure.ac: fix broken test for clock_gettime(CLOCK_MONOTONIC,ts) [#1777 follow-up] Signed-off-by: Jim Klimov --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f9b376e14f..f32de9e8b0 100644 --- a/configure.ac +++ b/configure.ac @@ -861,7 +861,7 @@ AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC,ts)], ], [struct timespec monoclock_ts; int got_monoclock = clock_gettime(CLOCK_MONOTONIC, &monoclock_ts); -if (ts.tv_sec < 0 || ts.tv_nsec < 0) return 1])], +if (monoclock_ts.tv_sec < 0 || monoclock_ts.tv_nsec < 0) return 1])], [ac_cv_func_clock_gettime=yes], [ac_cv_func_clock_gettime=no] )]) AS_IF([test x"${ac_cv_func_clock_gettime}" = xyes], From e39f10f8895ecf7ad1d2610ce09b4b97180423b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 10:53:20 +0200 Subject: [PATCH 0889/1232] Introduce nuttimetest (sanity-check difftime*() methods, etc.) [#2007, #1777] Signed-off-by: Jim Klimov --- tests/.gitignore | 3 + tests/Makefile.am | 4 ++ tests/nuttimetest.c | 154 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 tests/nuttimetest.c diff --git a/tests/.gitignore b/tests/.gitignore index a8aa04a5c3..876e375e29 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -13,6 +13,9 @@ /nutlogtest /nutlogtest.log /nutlogtest.trs +/nuttimetest +/nuttimetest.log +/nuttimetest.trs /getvaluetest /getvaluetest.log /getvaluetest.trs diff --git a/tests/Makefile.am b/tests/Makefile.am index 3a3b16871d..c063f6dca2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -40,6 +40,10 @@ else TESTS += nutlogtest endif +TESTS += nuttimetest +nuttimetest_SOURCES = nuttimetest.c +nuttimetest_LDADD = $(top_builddir)/common/libcommon.la + # Separate the .deps of other dirs from this one LINKED_SOURCE_FILES = hidparser.c diff --git a/tests/nuttimetest.c b/tests/nuttimetest.c new file mode 100644 index 0000000000..49e2264298 --- /dev/null +++ b/tests/nuttimetest.c @@ -0,0 +1,154 @@ +/* nuttimetest.c - test custom NUT routines for time comparison and manipulation + * + * Copyright (C) + * 2023 Jim Klimov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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 "config.h" +#include "common.h" +#include "nut_stdint.h" +#include "nut_float.h" + +#include +#include + +static int check_difftime() +{ + time_t tv1, tv2; + double d1, d2; + int res = 0; + + printf("=== %s(time_t):\t", __func__); + + /* Often time_t is a long int, maybe signed */ + tv1 = 5; + printf(" tv1=%" PRIiMAX, (intmax_t)tv1); + + tv2 = 8; + printf(" tv2=%" PRIiMAX, (intmax_t)tv2); + + /* like in difftime(): (double)seconds elapsed time between older tv2 and newer tv1 */ + d1 = difftime(tv1, tv2); + if (!d_equal(d1, -3)) + res++; + printf(" => diff1(tv1, tv2)=%f (%s)", d1, d_equal(d1, -3) ? "OK" : "FAIL"); + + d2 = difftime(tv2, tv1); + if (!d_equal(d2, 3)) + res++; + printf(" => diff2(tv2, tv1)=%f (%s)", d2, d_equal(d2, 3) ? "OK" : "FAIL"); + + if (!d_equal(d1, -d2)) { + printf(" => diff1 != -diff2 (FAIL)\n"); + res++; + } else { + printf(" => diff1 == -diff2 (OK)\n"); + } + + return res; +} + +static int check_difftimeval() +{ + struct timeval tv1, tv2; + double d1, d2; + int res = 0; + + printf("=== %s(struct timeval):\t", __func__); + + tv1.tv_sec = 5; + tv1.tv_usec = 900000; + printf(" tv1=%" PRIiMAX ".%06" PRIiMAX, (intmax_t)tv1.tv_sec, (intmax_t)tv1.tv_usec); + + tv2.tv_sec = 8; + tv2.tv_usec = 230000; + printf(" tv2=%" PRIiMAX ".%06" PRIiMAX, (intmax_t)tv2.tv_sec, (intmax_t)tv2.tv_usec); + + /* like in difftime(): (double)seconds elapsed time between older tv2 and newer tv1 */ + d1 = difftimeval(tv1, tv2); + if (!d_equal(d1, -2.33)) + res++; + printf(" => diff1(tv1, tv2)=%f (%s)", d1, d_equal(d1, -2.33) ? "OK" : "FAIL"); + + d2 = difftimeval(tv2, tv1); + if (!d_equal(d2, 2.33)) + res++; + printf(" => diff2(tv2, tv1)=%f (%s)", d2, d_equal(d2, 2.33) ? "OK" : "FAIL"); + + if (!d_equal(d1, -d2)) { + printf(" => diff1 != -diff2 (FAIL)\n"); + res++; + } else { + printf(" => diff1 == -diff2 (OK)\n"); + } + + return res; +} + +static int check_difftimespec() +{ + int res = 0; +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC + struct timespec tv1, tv2; + double d1, d2; + + printf("=== %s(struct timespec):\t", __func__); + + tv1.tv_sec = 5; + tv1.tv_nsec = 900000000; + printf(" tv1=%" PRIiMAX ".%09" PRIiMAX, (intmax_t)tv1.tv_sec, (intmax_t)tv1.tv_nsec); + + tv2.tv_sec = 8; + tv2.tv_nsec = 230000; + printf(" tv2=%" PRIiMAX ".%09" PRIiMAX, (intmax_t)tv2.tv_sec, (intmax_t)tv2.tv_nsec); + + /* like in difftime(): (double)seconds elapsed time between older tv2 and newer tv1 */ + d1 = difftimespec(tv1, tv2); + if (!d_equal(d1, -2.10023)) + res++; + printf(" => diff1(tv1, tv2)=%f (%s)", d1, d_equal(d1, -2.10023) ? "OK" : "FAIL"); + + d2 = difftimespec(tv2, tv1); + if (!d_equal(d2, 2.10023)) + res++; + printf(" => diff2(tv2, tv1)=%f (%s)", d2, d_equal(d2, 2.10023) ? "OK" : "FAIL"); + + if (!d_equal(d1, -d2)) { + printf(" => diff1 != -diff2 (FAIL)\n"); + res++; + } else { + printf(" => diff1 == -diff2 (OK)\n"); + } +#else + printf("=== %s(struct timespec):\tSKIP: NOT IMPLEMENTED for this build (not HAVE_CLOCK_GETTIME or not HAVE_CLOCK_MONOTONIC)\n", __func__); +#endif + + return res; +} + +int main(void) +{ + int ret = 0; + + ret += check_difftime(); + ret += check_difftimeval(); + ret += check_difftimespec(); + + return (ret != 0); +} From a8a300b0a3918ac31e82294a234c739e6a0a5cb7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 11:08:52 +0200 Subject: [PATCH 0890/1232] NEWS: announce support for state entry timestamping [#2010] Signed-off-by: Jim Klimov --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 031b826ee6..69d8558fea 100644 --- a/NEWS +++ b/NEWS @@ -89,6 +89,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. of recent codebase solves their practical issues. For "quick tests", a shortcut operation `./ci_build.sh inplace` was added [#1714] + - State tree structure and methods (including "dstate" wrapper for common + driver internals) was enhanced with time-stamping of last modification + (setting, changing, deleting the value or some fields in an entry): + this allows to detect stale information in a centralized fashion [#2010] + - We lacked log information about changes of chroot jail (uncommon) and of UID/GID (everywhere), which makes troubleshooting harder (e.g. lack of access to config files or USB device nodes). Now we have it [#1694] From f6f9e63863cc56fe5e9ad1d149bb14500ae32742 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 11:09:22 +0200 Subject: [PATCH 0891/1232] NEWS: move apcupsd fixes mis-placed into 2.8.0 notes block [#2007] Signed-off-by: Jim Klimov --- NEWS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 69d8558fea..3334786ef7 100644 --- a/NEWS +++ b/NEWS @@ -121,6 +121,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - powercom driver should now try harder to refresh data from device [#356] + - apcupsd-ups: + * improvement for `POLL_INTERVAL_MIN` from PR #797 was buggy [#2007] + * fix to clean obsoleted readings (if any) AFTER getting new info from an + `apcupsd` daemon, to avoid the gap when NUT driver knows nothing [#2007] + - NUT for Windows: * Ability to build NUT for Windows, last tackled with a branch based on NUT v2.6.5 a decade ago, has been revived with the 2.8.x era codebase [#5]. @@ -620,11 +625,6 @@ refer to this change set (too long in the making) as NUT 2.7.5. - the powerpanel driver now also supports CyberPower OR1500LCDRTXL2U with serial cable [PR #538] - - apcupsd-ups: - * improvement for `POLL_INTERVAL_MIN` from PR #797 was buggy [#2007] - * fix to clean obsoleted readings (if any) AFTER getting new info from an - `apcupsd` daemon, to avoid the gap when NUT driver knows nothing [#2007] - - powercom driver: implement `nobt` config parameter to skip battery check on initialization/startup [PR #1256] From 67907f5e86799249be78a1ca0777eeffb669766f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 11:14:42 +0200 Subject: [PATCH 0892/1232] docs/Makefile.am: spellcheck LICENSE-DCO file [#1995 follow-up] Signed-off-by: Jim Klimov --- docs/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index f602ce4d64..e05aae8bf2 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -274,7 +274,7 @@ if HAVE_ASPELL SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../INSTALL.nut ../UPGRADING ../NEWS \ ../TODO ../scripts/ufw/README ../scripts/augeas/README ../lib/README \ ../tools/nut-scanner/README \ - ../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3 + ../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3 ../LICENSE-DCO # Directory SPELLCHECK_SRC files are relative to. Overriden by other Makefiles. SPELLCHECK_DIR = $(srcdir) From acc5c356155c120fb91ce656dafed4dc01e93879 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 18:41:00 +0200 Subject: [PATCH 0893/1232] drivers/apcupsd-ups.c: fix use of INVALID_FD_SOCK() macro over complex expression [#2007] Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 1751bf0daf..cf6443f385 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -189,7 +189,7 @@ static int getdata(void) state_get_timestamp((st_tree_timespec_t *)&start); - if (INVALID_FD_SOCK( p.fd = socket(AF_INET, SOCK_STREAM, 0) )) + if (INVALID_FD_SOCK( (p.fd = socket(AF_INET, SOCK_STREAM, 0)) )) { upsdebugx(1,"socket error"); /* return -1; */ From 29724e1a4f6b993b7547485522f4ded71796a501 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 18:46:36 +0200 Subject: [PATCH 0894/1232] common/state.c: update comment for st_tree_node_compare_timestamp() [#2007] Signed-off-by: Jim Klimov --- common/state.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/state.c b/common/state.c index 793a1c6f1b..40ab4e8fa4 100644 --- a/common/state.c +++ b/common/state.c @@ -171,6 +171,11 @@ int st_tree_node_compare_timestamp( if (!cutoff) return -3; + /* Like in difftime(), the first arg is "finish" and + * the second arg is "start" of a time range (below), + * so if the diff is negative, then "lastset" happened + * before "cutoff": + */ #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC d = difftimespec(node->lastset, *cutoff); #else From d52971ecdda4b74273025b23e7a2f2eadc39521d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 4 Aug 2023 18:47:50 +0200 Subject: [PATCH 0895/1232] common/state.c: in state_delinfo_olderthan() do upsdebugx(6,...) that we are deleting an entry because it is too old [#2007] Signed-off-by: Jim Klimov --- common/state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/state.c b/common/state.c index 40ab4e8fa4..6eaf18ab6c 100644 --- a/common/state.c +++ b/common/state.c @@ -253,6 +253,7 @@ int state_delinfo_olderthan(st_tree_t **nptr, const char *var, const st_tree_tim upsdebugx(6, "%s: not deleting recently updated variable [%s]", __func__, var); return 0; } + upsdebugx(6, "%s: deleting variable [%s] last updated too long ago", __func__, var); /* whatever is on the left, hang it off current right */ st_tree_node_add(&node->right, node->left); From db0272a9444228944bfa2daf1b7fd6cda4a39718 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 14:05:07 +0200 Subject: [PATCH 0896/1232] drivers/nutdrv_qx.c: convert to ARMAC_READ_SIZE as a macro Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 5c13460461..b1f236c663 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1759,10 +1759,10 @@ static void *ablerex_subdriver_fun(USBDevice_t *device) * Richcomm Technologies, Inc. Dec 27 2005 ver 1.1." Maybe other Richcomm UPSes * would work with this - better than with the richcomm_usb driver. */ +#define ARMAC_READ_SIZE 6 static int armac_command(const char *cmd, char *buf, size_t buflen) { - const int READ_SIZE = 6; - char tmpbuf[READ_SIZE]; + char tmpbuf[ARMAC_READ_SIZE]; int ret = 0; size_t i, bufpos; const size_t cmdlen = strlen(cmd); @@ -1792,8 +1792,8 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) /* Cleanup buffer before sending a new command */ for (i = 0; i < 10; i++) { ret = usb_interrupt_read(udev, 0x81, - (usb_ctrl_charbuf)tmpbuf, READ_SIZE, 100); - if (ret != READ_SIZE) { + (usb_ctrl_charbuf)tmpbuf, ARMAC_READ_SIZE, 100); + if (ret != ARMAC_READ_SIZE) { // Timeout - buffer is clean. break; } @@ -1827,17 +1827,17 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) memset(buf, 0, buflen); bufpos = 0; - while (bufpos + READ_SIZE < buflen) { + while (bufpos + ARMAC_READ_SIZE < buflen) { size_t bytes_available; /* Read data in 6-byte chunks */ ret = usb_interrupt_read(udev, 0x81, - (usb_ctrl_charbuf)tmpbuf, READ_SIZE, 1000); + (usb_ctrl_charbuf)tmpbuf, ARMAC_READ_SIZE, 1000); /* Any errors here mean that we are unable to read a reply * (which will happen after successfully writing a command * to the UPS) */ - if (ret != READ_SIZE) { + if (ret != ARMAC_READ_SIZE) { /* NOTE: If end condition is invalid for particular UPS we might make one * request more and get this error. If bufpos > (say) 10 this could be ignored * and the reply correctly read. */ @@ -1868,9 +1868,9 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) break; } - if (bytes_available > (size_t)(READ_SIZE - 1)) { + if (bytes_available > ARMAC_READ_SIZE - 1) { /* Single interrupt transfer has 1 control + 5 data bytes */ - bytes_available = READ_SIZE - 1; + bytes_available = ARMAC_READ_SIZE - 1; } /* Copy bytes into the final buffer while detecting end of line - \r */ From 3ed1220abd2e9ec39bb2655175a547686074ba7c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 18:56:54 +0200 Subject: [PATCH 0897/1232] server/upsd.c, NEWS, UPGRADING: listen_add(): firstaddr should remain first [#2012] Signed-off-by: Jim Klimov --- NEWS | 4 ++++ UPGRADING | 6 ++++++ server/upsd.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 3334786ef7..6dffcfea54 100644 --- a/NEWS +++ b/NEWS @@ -278,6 +278,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * added support for `NUT_QUIET_INIT_SSL` environment variable to hide the infamous "Init SSL without certificate database" warning [#1662] + - The `upsd.conf` listing of `LISTEN` addresses was previously inverted + (the last listed address was applied first), which was counter-intuitive + and fixed for this release [#2012] + - sstate (server state, e.g. upsd) should now "PING" drivers also if they last reported themselves as "stale" (and might later crash) so their connections would be terminated if really no longer active [#1626] diff --git a/UPGRADING b/UPGRADING index 10b87c0968..72a1de5de5 100644 --- a/UPGRADING +++ b/UPGRADING @@ -65,6 +65,12 @@ Changes from 2.8.0 to 2.8.1 the packaging recipes may use NUT source-code facilities and package just symlinks as relevant for each distro separately [#1462, #1504] +- The `upsd.conf` listing of `LISTEN` addresses was previously inverted + (the last listed address was applied first), which was counter-intuitive + and fixed for this release. If user configurations somehow relied on this + order (e.g. to prioritize IPv6 vs IPv4 listeners), configuration changes + may be needed. [#2012] + - Added support for `make sockdebug` for easier developer access to the tool; also if `configure --with-dev` is in effect, it would now be installed to the configured `libexec` location. A man page was also added. [#1936] diff --git a/server/upsd.c b/server/upsd.c index 8c66661b62..f2de2dc233 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -237,9 +237,15 @@ void listen_add(const char *addr, const char *port) server->addr = xstrdup(addr); server->port = xstrdup(port); server->sock_fd = ERROR_FD_SOCK; - server->next = firstaddr; + server->next = NULL; - firstaddr = server; + if (firstaddr) { + stype_t *tmp; + for (tmp = firstaddr; tmp->next; tmp = tmp->next); + tmp->next = server; + } else { + firstaddr = server; + } upsdebugx(3, "listen_add: added %s:%s", server->addr, server->port); } From a575c809f86ee7458acf69eb3e2c09aa5c20d01d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 19:04:09 +0200 Subject: [PATCH 0898/1232] NEWS: typo fix Signed-off-by: Jim Klimov --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 6dffcfea54..2a99a07bfc 100644 --- a/NEWS +++ b/NEWS @@ -62,7 +62,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. too low. As issue #1455 and PR #1495 found, in two cases the called commands did "meaningfully" modify data -- so without debug logs the program misbehaved. A known regression for `upscode2` driver; might - be or not be a problem with `upsd` driver in NUT v2.8.0 release, + be or not be a problem with `upsd` server in NUT v2.8.0 release, fixed for NUT v2.8.1. * A table in `cyberpower-mib` (for `snmp-ups` driver) sources was arranged in NUT v2.8.0 release in a way that precluded the driver From 7bf7f0c6a9f78e9a6bd8d7277a24874a472405c3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 19:04:51 +0200 Subject: [PATCH 0899/1232] server/upsd.c: server_load(): log if defaulting to localhost (IPv4/IPv6) due to lack of LISTEN directive [#2012] Signed-off-by: Jim Klimov --- server/upsd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/upsd.c b/server/upsd.c index f2de2dc233..2004f8c9bb 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -694,13 +694,16 @@ void server_load(void) { stype_t *server; - /* default behaviour if no LISTEN addres has been specified */ + /* default behaviour if no LISTEN address has been specified */ if (!firstaddr) { + /* Note: default opt_af==AF_UNSPEC so not constrained to only one protocol */ if (opt_af != AF_INET) { + upsdebugx(1, "%s: No LISTEN configuration provided, will try IPv6 localhost", __func__); listen_add("::1", string_const(PORT)); } if (opt_af != AF_INET6) { + upsdebugx(1, "%s: No LISTEN configuration provided, will try IPv4 localhost", __func__); listen_add("127.0.0.1", string_const(PORT)); } } From f068e8a8a9f3e2b3fee91794990c89096415cab6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 19:40:03 +0200 Subject: [PATCH 0900/1232] server/upsd.c: setuptcp(): warn if we bound to one address for a name and end the loop while there seem to be more resolved addresses for it [#2012] Signed-off-by: Jim Klimov --- server/upsd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/upsd.c b/server/upsd.c index 2004f8c9bb..17155dd9c7 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -312,6 +312,20 @@ static void setuptcp(stype_t *server) continue; } + if (ai->ai_next) { + char ipaddrbuf[SMALLBUF]; + const char *ipaddr; + snprintf(ipaddrbuf, sizeof(ipaddrbuf), " as "); + ipaddr = inet_ntop(ai->ai_family, ai->ai_addr, + ipaddrbuf + strlen(ipaddrbuf), + sizeof(ipaddrbuf)); + upslogx(LOG_WARNING, + "setuptcp: bound to %s%s but there seem to be " + "further (ignored) addresses resolved for this name", + server->addr, + ipaddr == NULL ? "" : ipaddrbuf); + } + server->sock_fd = sock_fd; break; } From 534f153f2005bfdb421d1440bc7a823ac38845a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 20:36:11 +0200 Subject: [PATCH 0901/1232] server/upsd.c: refactor server_free() with a new stype_free() [#2012] Signed-off-by: Jim Klimov --- server/upsd.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 17155dd9c7..eb99df810c 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -250,6 +250,20 @@ void listen_add(const char *addr, const char *port) upsdebugx(3, "listen_add: added %s:%s", server->addr, server->port); } +/* Close the connection if needed and free the allocated memory. + * WARNING: it is up to the caller to rewrite the "next" pointer + * in whoever points to this server instance (if needed)! */ +static void stype_free(stype_t *server) +{ + if (VALID_FD_SOCK(server->sock_fd)) { + close(server->sock_fd); + } + + free(server->addr); + free(server->port); + free(server); +} + /* create a listening socket for tcp connections */ static void setuptcp(stype_t *server) { @@ -739,14 +753,7 @@ void server_free(void) /* cleanup server fds */ for (server = firstaddr; server; server = snext) { snext = server->next; - - if (VALID_FD_SOCK(server->sock_fd)) { - close(server->sock_fd); - } - - free(server->addr); - free(server->port); - free(server); + stype_free(server); } firstaddr = NULL; From 22b51fc79b345861722dd52b06bdd783d2d36dd3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 20:51:25 +0200 Subject: [PATCH 0902/1232] server/upsd.c, NEWS, UPGRADING: setuptcp(): when asked to LISTEN on IPv6 addresses, try to disable IPv4-mapping support [#2012] Signed-off-by: Jim Klimov --- NEWS | 5 +++++ UPGRADING | 8 ++++++++ server/upsd.c | 11 +++++++++++ 3 files changed, 24 insertions(+) diff --git a/NEWS b/NEWS index 2a99a07bfc..5b21a56099 100644 --- a/NEWS +++ b/NEWS @@ -282,6 +282,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. (the last listed address was applied first), which was counter-intuitive and fixed for this release [#2012] + - The `upsd` configured to listen on IPv6 addresses should handle only + IPv6 (and not IPv4-mappings) to avoid surprises and insecurity; it + would warn if a hostname resolves to several addresses (and would only + listen on the first hit, as before in such cases) [#2012] + - sstate (server state, e.g. upsd) should now "PING" drivers also if they last reported themselves as "stale" (and might later crash) so their connections would be terminated if really no longer active [#1626] diff --git a/UPGRADING b/UPGRADING index 72a1de5de5..03471a0660 100644 --- a/UPGRADING +++ b/UPGRADING @@ -71,6 +71,14 @@ Changes from 2.8.0 to 2.8.1 order (e.g. to prioritize IPv6 vs IPv4 listeners), configuration changes may be needed. [#2012] +- The `upsd` configured to listen on IPv6 addresses should handle only + IPv6 (and not IPv4-mappings like it might have done before) to avoid + surprises and insecurity -- if user configurations somehow relied on + this dual support, configuration changes may be needed to specify both + desired IP addresses. Note that the daemon logs would warn if a hostname + resolves to several addresses (and would only listen on the first hit, + as it did before in such cases) [#2012] + - Added support for `make sockdebug` for easier developer access to the tool; also if `configure --with-dev` is in effect, it would now be installed to the configured `libexec` location. A man page was also added. [#1936] diff --git a/server/upsd.c b/server/upsd.c index eb99df810c..23ec4df4e8 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -303,6 +303,17 @@ static void setuptcp(stype_t *server) fatal_with_errno(EXIT_FAILURE, "setuptcp: setsockopt"); } + /* Ordinarily we request that IPv6 listeners handle only IPv6. + * TOTHINK: Does any platform need `#ifdef IPV6_V6ONLY` given + * that we apparently already have AF_INET6 OS support everywhere? + */ + if (ai->ai_family == AF_INET6) { + if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one, sizeof(one)) != 0) { + upsdebug_with_errno(3, "setuptcp: setsockopt IPV6_V6ONLY"); + /* ack, ignore */ + } + } + if (bind(sock_fd, ai->ai_addr, ai->ai_addrlen) < 0) { upsdebug_with_errno(3, "setuptcp: bind"); close(sock_fd); From 76f3a97f67d14611febe6b65f922156eb08bdbdc Mon Sep 17 00:00:00 2001 From: Craig Holyoak Date: Sun, 6 Aug 2023 08:19:33 +1000 Subject: [PATCH 0903/1232] Moved additional ups.status to ups.alarm --- drivers/cyberpower-mib.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index cbb563440f..c83395625c 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -75,10 +75,10 @@ static info_lkp_t cyberpower_battrepl_status[] = { { 0, NULL, NULL, NULL } }; -static info_lkp_t cyberpower_ups_status[] = { - { 1, "", NULL, NULL }, /* Normal */ - { 2, "OH", NULL, NULL }, /* Overheat */ - { 3, "HW", NULL, NULL }, /* Hardware Fault */ +static info_lkp_t cyberpower_ups_alarm_info[] = { + { 1, "", NULL, NULL }, /* Normal */ + { 2, "Temperature too high!", NULL, NULL }, /* Overheat */ + { 3, "Internal UPS fault!", NULL, NULL }, /* Hardware Fault */ { 0, NULL, NULL, NULL } }; @@ -132,13 +132,14 @@ static snmp_info_t cyberpower_mib[] = { SU_FLAG_OK | SU_STATUS_CAL, &cyberpower_cal_status[0] }, { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.2.5.0", "", SU_FLAG_OK | SU_STATUS_RB, &cyberpower_battrepl_status[0] }, - { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.10.1.0", "", - SU_FLAG_OK, &cyberpower_ups_status[0] }, { "ups.load", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.4.2.3.0", "", 0, NULL }, { "ups.temperature", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.10.2.0", "", SU_FLAG_OK, NULL }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.10.1.0", "", + SU_FLAG_OK, &cyberpower_ups_alarm_info[0] }, + /* Battery runtime is expressed in seconds */ { "battery.runtime", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "", 0, NULL }, From a904962dfe7075697f42bfb883f97ccc1b5815a7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 5 Aug 2023 22:04:40 +0200 Subject: [PATCH 0904/1232] server/upsd.c and docs/config examples: handle "LISTEN *" deterministically (for both IPv4 and IPv6 if we can) [#2012] Signed-off-by: Jim Klimov --- NEWS | 6 ++ UPGRADING | 6 ++ conf/upsd.conf.sample | 12 +++ docs/config-notes.txt | 6 ++ docs/man/upsd.conf.txt | 14 ++- docs/security.txt | 6 ++ scripts/augeas/nutupsdconf.aug.in | 10 +- server/upsd.c | 173 +++++++++++++++++++++++++++++- 8 files changed, 227 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 5b21a56099..1525607348 100644 --- a/NEWS +++ b/NEWS @@ -287,6 +287,12 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. would warn if a hostname resolves to several addresses (and would only listen on the first hit, as before in such cases) [#2012] + - A definitive behavior for `LISTEN *` directives became specified, to try + handling both IPv4 and IPv6 "any" address (subject to `upsd` CLI options + to only choose one, and to OS abilities); this use-case may be practically + implemented as a single IPv6 socket on systems with enabled "dual-stack" + support or as two separate listening sockets [#2012] + - sstate (server state, e.g. upsd) should now "PING" drivers also if they last reported themselves as "stale" (and might later crash) so their connections would be terminated if really no longer active [#1626] diff --git a/UPGRADING b/UPGRADING index 03471a0660..7a92aae3d4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -79,6 +79,12 @@ Changes from 2.8.0 to 2.8.1 resolves to several addresses (and would only listen on the first hit, as it did before in such cases) [#2012] +- A definitive behavior for `LISTEN *` directives became specified, to try + handling both IPv4 and IPv6 "any" address (subject to `upsd` CLI options + to only choose one, and to OS abilities); this use-case may be practically + implemented as a single IPv6 socket on systems with enabled "dual-stack" + support or as two separate listening sockets [#2012] + - Added support for `make sockdebug` for easier developer access to the tool; also if `configure --with-dev` is in effect, it would now be installed to the configured `libexec` location. A man page was also added. [#1936] diff --git a/conf/upsd.conf.sample b/conf/upsd.conf.sample index 8c8f95a634..29ed500127 100644 --- a/conf/upsd.conf.sample +++ b/conf/upsd.conf.sample @@ -64,6 +64,12 @@ # Note that it is not true for Windows platforms. You shouldn't use IPv6 in # your configuration files unless you have IPv6 installed. # +# As a special case, `LISTEN * ` (with an asterisk) would try +# to listen on "ANY" IP address for both IPv4 (0.0.0.0) and IPv6 (::0), +# subject to `upsd` command-line arguments or OS/kernel configuration. +# If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 +# then there would be one listening socket for both address types. +# # One or more LISTEN statements give the IP address (or name that # resolves to such an address) for upsd to listen on, optionally with # a port number. @@ -74,6 +80,12 @@ # # This will only be read at startup of upsd. If you make changes here, # you'll need to restart upsd, as reload will have no effect. +# +# Please note that older NUT releases could have been using the "dual-stack" +# mode, if provided by the system. Current versions (since NUT v2.8.1 release) +# try to restrict their listening sockets to only support IPv6 addresses and +# so avoid IPv4-mapped mode, except when handling the special `LISTEN * ` +# directive. # ======================================================================= # MAXCONN diff --git a/docs/config-notes.txt b/docs/config-notes.txt index 5f9f7a236d..ec24e1515f 100644 --- a/docs/config-notes.txt +++ b/docs/config-notes.txt @@ -295,6 +295,12 @@ want `upsd` to listen on for connections, optionally with a port number. LISTEN 127.0.0.1 3493 LISTEN ::1 3493 +As a special case, `LISTEN * ` (with an asterisk) would try +to listen on "ANY" IP address for both IPv4 (`0.0.0.0`) and IPv6 (`::0`), +subject to `upsd` command-line arguments or OS/kernel configuration. +If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 +then there would be one listening socket for both address types. + NOTE: Refer to the NUT user manual <> for information on how to access and secure upsd clients connections. diff --git a/docs/man/upsd.conf.txt b/docs/man/upsd.conf.txt index 8287e54a56..57618b9b0b 100644 --- a/docs/man/upsd.conf.txt +++ b/docs/man/upsd.conf.txt @@ -70,8 +70,12 @@ Multiple LISTEN addresses may be specified. The default is to bind to compiled in). + To listen on all available interfaces, you may also use '0.0.0.0' for IPv4 and -and '::' for IPv6. - +and '::' for IPv6. As a special case, `LISTEN * ` (with an asterisk) +would try to listen on both IPv4 (`0.0.0.0`) and IPv6 (`::0`) wild-card IP +addresses, subject to `upsd` command-line arguments or OS/kernel configuration. +If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 +then there would be one listening socket for both address types. ++ LISTEN 127.0.0.1 LISTEN 192.168.50.1 LISTEN myhostname.mydomain @@ -80,6 +84,12 @@ and '::' for IPv6. + This parameter will only be read at startup. You'll need to restart (rather than reload) upsd to apply any changes made here. ++ +Please note that older NUT releases could have been using the "dual-stack" +mode, if provided by the system. Current versions (since NUT v2.8.1 release) +try to restrict their listening sockets to only support IPv6 addresses and +so avoid IPv4-mapped mode, except when handling the special `LISTEN * ` +directive. "MAXCONN 'connections'":: diff --git a/docs/security.txt b/docs/security.txt index 51a50c5fcc..7d69aa0bf3 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -234,6 +234,12 @@ compiled in). LISTEN ::1 LISTEN 2001:0db8:1234:08d3:1319:8a2e:0370:7344 +As a special case, `LISTEN * ` (with an asterisk) would try +to listen on "ANY" IP address for both IPv4 (`0.0.0.0`) and IPv6 (`::0`), +subject to `upsd` command-line arguments or OS/kernel configuration. +If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 +then there would be one listening socket for both address types. + This parameter will only be read at startup. You'll need to restart (rather than reload) `upsd` to apply any changes made here. diff --git a/scripts/augeas/nutupsdconf.aug.in b/scripts/augeas/nutupsdconf.aug.in index 35bf896f09..dff4fef435 100644 --- a/scripts/augeas/nutupsdconf.aug.in +++ b/scripts/augeas/nutupsdconf.aug.in @@ -55,8 +55,14 @@ let upsd_certfile = [ opt_spc . key "CERTFILE" . sep_spc . store path . eol ] * ALLOW_NO_DEVICE Boolean * STATEPATH path * LISTEN interface port - * Multiple LISTEN addresses may be specified. The default is to bind to 0.0.0.0 if no LISTEN addresses are specified. - * LISTEN 127.0.0.1 LISTEN 192.168.50.1 LISTEN ::1 LISTEN 2001:0db8:1234:08d3:1319:8a2e:0370:7344 + * Multiple lines each with one LISTEN address (or host name) and an optional + * port may be specified. The default is to bind to IPv4 and IPv6 "localhost" + * addresses (subject to CLI options `-4` or `-6` constraining IP version or + * OS kernel/configuration support), if no LISTEN addresses are specified. + * LISTEN 127.0.0.1 + * LISTEN 192.168.50.1 + * LISTEN ::1 + * LISTEN 2001:0db8:1234:08d3:1319:8a2e:0370:7344 * *************************************************************************) let upsd_other = upsd_maxage | upsd_trackingdelay | upsd_allow_no_device | upsd_statepath | upsd_listen_list | upsd_maxconn | upsd_certfile diff --git a/server/upsd.c b/server/upsd.c index 23ec4df4e8..3d1da59340 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -267,6 +267,8 @@ static void stype_free(stype_t *server) /* create a listening socket for tcp connections */ static void setuptcp(stype_t *server) { + /* Well, currently it is more a request than requirement... */ + static int require_IPV6_V6ONLY = 1; #ifdef WIN32 WSADATA WSAdata; WSAStartup(2,&WSAdata); @@ -275,8 +277,169 @@ static void setuptcp(stype_t *server) struct addrinfo hints, *res, *ai; int v = 0, one = 1; + if (VALID_FD_SOCK(server->sock_fd)) { + /* Alredy bound, e.g. thanks to 'LISTEN *' handling and injection + * into the list we loop over */ + upsdebugx(6, "setuptcp: SKIP bind to %s port %s: entry already initialized", + server->addr, server->port); + return; + } + upsdebugx(3, "setuptcp: try to bind to %s port %s", server->addr, server->port); + /* Special handling for `LISTEN * ` directive with literal asterisk: + * on systems with RFC-3493 (no relation!) support for "IPv4-mapped addresses" + * it suffices to LISTEN on "::" (aka "::0" or "0:0:0:0:0:0:0:0") and also + * get an IPv4 any-address listener. More so, they would conflict and + * listening on one such socket precludes listening on the other. On other + * systems (or with disabled mapping so IPv6 means IPv6 only) we need both. + * So we jump through some hoops: + * * Try to get IPv4 any-address, just to know if it is available right now; + * * Free it and try to get IPv6 any-address, and try to get again that + * IPv4 any-address (IFF it was available before but is not available now - + * not a problem). + * * Remember the entries used, to release later. + * For more details see https://github.com/networkupstools/nut/issues/2012 + */ + if (!strcmp(server->addr, "*")) { + stype_t *serverAnyV4 = NULL, *serverAnyV6 = NULL; + int canhaveAnyV4 = 0; + int canhaveAnyV6 = 0; + + /* For this use-case, we allow IPv6 to handle IPv4 if it can */ + int old_require_IPV6_V6ONLY = require_IPV6_V6ONLY; + require_IPV6_V6ONLY = (opt_af == AF_INET6); + + /* Note: default opt_af==AF_UNSPEC so not constrained to only one protocol */ + if (opt_af != AF_INET6) { + /* Not constrained to IPv6 */ + upsdebugx(1, "%s: handling 'LISTEN * %s' with IPv4 any-address support", + __func__, server->port); + serverAnyV4 = xcalloc(1, sizeof(*serverAnyV4)); + serverAnyV4->addr = xstrdup("0.0.0.0"); + serverAnyV4->port = xstrdup(server->port); + serverAnyV4->sock_fd = ERROR_FD_SOCK; + serverAnyV4->next = NULL; + } + + if (opt_af != AF_INET) { + /* Not constrained to IPv4 */ + upsdebugx(1, "%s: handling 'LISTEN * %s' with IPv6 any-address support", + __func__, server->port); + serverAnyV6 = xcalloc(1, sizeof(*serverAnyV6)); + serverAnyV6->addr = xstrdup("::0"); + serverAnyV6->port = xstrdup(server->port); + serverAnyV6->sock_fd = ERROR_FD_SOCK; + serverAnyV6->next = NULL; + } + + if (serverAnyV4) { + /* First pass to just check if we CAN have this listener now */ + setuptcp(serverAnyV4); + if (serverAnyV6) { + if (VALID_FD_SOCK(serverAnyV4->sock_fd)) { + upsdebugx(3, + "%s: Could bind to %s:%s trying to handle a 'LISTEN *' directive" + "; will release it for now to try IPv6", + __func__, serverAnyV4->addr, serverAnyV4->port); + canhaveAnyV4 = 1; + close(serverAnyV4->sock_fd); + serverAnyV4->sock_fd = ERROR_FD_SOCK; + /* Let the system know about the change: */ + /* usleep(100); */ + } else { + upsdebugx(3, + "%s: Could not bind to %s:%s trying to handle a 'LISTEN *' directive", + __func__, serverAnyV4->addr, serverAnyV4->port); + } + } /* else: just keep it, all done */ + } + + if (serverAnyV6) { + setuptcp(serverAnyV6); + if (VALID_FD_SOCK(serverAnyV6->sock_fd)) { + canhaveAnyV6 = 1; + } else { + upsdebugx(3, + "%s: Could not bind to %s:%s trying to handle a 'LISTEN *' directive", + __func__, serverAnyV6->addr, serverAnyV6->port); + } + + if (serverAnyV4 && canhaveAnyV4) { + /* Second pass to get this listener if we can (no IPv4-mapped IPv6 + * support was in force on this platform or its configuration) */ + upsdebugx(3, "%s: try taking IPv4 'ANY' again " + "(if dual-stack IPv6 'ANY' did not grab it)", __func__); + setuptcp(serverAnyV4); + if (INVALID_FD_SOCK(serverAnyV4->sock_fd)) { + upsdebugx(3, + "%s: Could not bind to IPv4 %s:%s after trying to bind to IPv6: " + "assuming dual-stack support on this system", + __func__, serverAnyV4->addr, serverAnyV4->port); + canhaveAnyV4 = 0; + } + } + } + + if (!canhaveAnyV4 && !canhaveAnyV6) { + fatalx(EXIT_FAILURE, + "Handling of 'LISTEN * %s' directive failed to bind to 'ANY' address", + server->port); + } + + /* Finalize our findings and reset to normal operation + * Note that at least one of these addresses is usable + * and we keep it (and replace original "server" entry + * keeping its place in the list). + */ + free(server->addr); + free(server->port); + if (canhaveAnyV4) { + upsdebugx(3, "%s: remembering IPv4 'ANY' instead of 'LISTEN *'", __func__); + server->addr = serverAnyV4->addr; + server->port = serverAnyV4->port; + server->sock_fd = serverAnyV4->sock_fd; + /* ...and keep whatever server->next there was */ + + /* Free the ghost, all needed info was relocated */ + free(serverAnyV4); + } else { + if (serverAnyV4) { + /* Free any contents there were too */ + stype_free(serverAnyV4); + } + } + serverAnyV4 = NULL; + + if (canhaveAnyV6) { + if (canhaveAnyV4) { + /* "server" already populated by excerpts from V4, attach to it */ + upsdebugx(3, "%s: also remembering IPv6 'ANY' instead of 'LISTEN *'", __func__); + serverAnyV6->next = server->next; + server->next = serverAnyV6; + } else { + /* Only retain V6 info */ + upsdebugx(3, "%s: remembering IPv6 'ANY' instead of 'LISTEN *'", __func__); + server->addr = serverAnyV6->addr; + server->port = serverAnyV6->port; + server->sock_fd = serverAnyV6->sock_fd; + /* ...and keep whatever server->next there was */ + + /* Free the ghost, all needed info was relocated */ + free(serverAnyV6); + } + } else { + if (serverAnyV6) { + /* Free any contents there were too */ + stype_free(serverAnyV6); + } + } + serverAnyV6 = NULL; + + require_IPV6_V6ONLY = old_require_IPV6_V6ONLY; + return; + } + memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = opt_af; @@ -303,11 +466,17 @@ static void setuptcp(stype_t *server) fatal_with_errno(EXIT_FAILURE, "setuptcp: setsockopt"); } - /* Ordinarily we request that IPv6 listeners handle only IPv6. + /* Ordinarily we request that IPv6 listeners handle only IPv6 + * (except when we handle `LISTEN *` as detailed above). + * Note we specifically try to ensure this when CLI requires + * IPv6-only behavior (even if we want "any" addr for `LISTEN *`). * TOTHINK: Does any platform need `#ifdef IPV6_V6ONLY` given * that we apparently already have AF_INET6 OS support everywhere? + * TOTHINK: Do we want to setsockopt() to explicitly allow dual-stack + * (perhaps counteracting OS default or customized configuration) + * when handling `LISTEN *` use-cases? */ - if (ai->ai_family == AF_INET6) { + if (ai->ai_family == AF_INET6 && (require_IPV6_V6ONLY || (opt_af == AF_INET6))) { if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one, sizeof(one)) != 0) { upsdebug_with_errno(3, "setuptcp: setsockopt IPV6_V6ONLY"); /* ack, ignore */ From bc14bf8f67c733eb446df087fa7f622d4eea66e2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 12 Aug 2023 18:12:48 +0200 Subject: [PATCH 0905/1232] drivers/apcsmart(-old).c: do not abort on bad caps, skip them like before [#2015] Closes: #2015 Signed-off-by: Jim Klimov --- NEWS | 2 ++ drivers/apcsmart-old.c | 27 ++++++++++++++++----------- drivers/apcsmart.c | 26 ++++++++++++++++---------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/NEWS b/NEWS index 3334786ef7..14fa9ecfbf 100644 --- a/NEWS +++ b/NEWS @@ -82,6 +82,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. and would not wait for one driver to complete initialization before starting another in case of mass-management loop to start all drivers (without specifying the single device) [#1759, #1806, #1875] + * The `apcsmart` and `apcsmart-old` handled invalid data too zealously + and aborted instead of skipping over it, like they did before [#2015] - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an diff --git a/drivers/apcsmart-old.c b/drivers/apcsmart-old.c index 197a7b2537..d577f73154 100644 --- a/drivers/apcsmart-old.c +++ b/drivers/apcsmart-old.c @@ -25,7 +25,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "2.30" +#define DRIVER_VERSION "2.31" static upsdrv_info_t table_info = { "APC command table", @@ -373,32 +373,37 @@ static void do_capabilities(void) /* check for idiocy */ if (ptr >= endtemp) { - /* if we expected this, just ignore it */ if (quirk_capability_overflow) return; fatalx(EXIT_FAILURE, "Capability string has overflowed\n" - "Please report this error\n" + "Please report this error with device details\n" "ERROR: capability overflow!" ); } + entptr = &ptr[4]; cmd = ptr[0]; loc = ptr[1]; + if (ptr[2] < 48 || ptr[3] < 48) { - upsdebugx(0, - "%s: nument (%d) or entlen (%d) out of range", - __func__, (ptr[2] - 48), (ptr[3] - 48)); - fatalx(EXIT_FAILURE, - "nument or entlen out of range\n" - "Please report this error\n" - "ERROR: capability overflow!"); + upsdebugx(3, + "%s: SKIP: nument (%d) or entlen (%d) " + "out of range for cmd %d at loc %d", + __func__, (ptr[2] - 48), (ptr[3] - 48), + cmd, loc); + + /* just ignore it as we did for ages (the + * rest of loop cycle would be no-op anyway) + */ + ptr = entptr; + continue; } + nument = (size_t)ptr[2] - 48; entlen = (size_t)ptr[3] - 48; - entptr = &ptr[4]; vt = vartab_lookup_char(cmd); valid = vt && ((loc == upsloc) || (loc == '4')); diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 7867d3eeb4..f38d2911e4 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -36,7 +36,7 @@ #include "apcsmart_tabs.h" #define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "3.30" +#define DRIVER_VERSION "3.31" #ifdef WIN32 # ifndef ECANCELED @@ -1024,25 +1024,31 @@ static void apc_getcaps(int qco) /* if we expected this, just ignore it */ if (qco) return; - fatalx(EXIT_FAILURE, "capability string has overflowed, please report this error !"); + fatalx(EXIT_FAILURE, + "capability string has overflowed, " + "please report this error with device details!"); } + entptr = &ptr[4]; cmd = ptr[0]; loc = ptr[1]; if (ptr[2] < 48 || ptr[3] < 48) { - upsdebugx(0, - "%s: nument (%d) or entlen (%d) out of range", - __func__, (ptr[2] - 48), (ptr[3] - 48)); - fatalx(EXIT_FAILURE, - "nument or entlen out of range\n" - "Please report this error\n" - "ERROR: capability overflow!"); + upsdebugx(3, + "%s: SKIP: nument (%d) or entlen (%d) " + "out of range for cmd %d at loc %d", + __func__, (ptr[2] - 48), (ptr[3] - 48), + cmd, loc); + + /* just ignore it as we did for ages (the + * rest of loop cycle would be no-op anyway) + */ + ptr = entptr; + continue; } nument = (size_t)ptr[2] - 48; entlen = (size_t)ptr[3] - 48; - entptr = &ptr[4]; vt = vt_lookup_char(cmd); valid = vt && ((loc == upsloc) || (loc == '4')) && !(vt->flags & APC_PACK); From a8f4586b0a52cb2d4950b88690eeb04394ce2841 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 13 Aug 2023 00:42:10 +0200 Subject: [PATCH 0906/1232] drivers/cyberpower-mib.c: bump version for new entries Signed-off-by: Jim Klimov --- drivers/cyberpower-mib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index c83395625c..d240b5c0ec 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -24,7 +24,7 @@ #include "cyberpower-mib.h" -#define CYBERPOWER_MIB_VERSION "0.53" +#define CYBERPOWER_MIB_VERSION "0.54" #define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" /* CPS-MIB::ups */ From 4fd53afd5cb73eba28fc288e341ef47afd753423 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 13 Aug 2023 00:44:05 +0200 Subject: [PATCH 0907/1232] NEWS: cyberpower-mib.c supports more data points now [#1982] Signed-off-by: Jim Klimov --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 3334786ef7..17ccac1fa7 100644 --- a/NEWS +++ b/NEWS @@ -165,6 +165,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. of valid outlet status values [#1871] * `cyberpower-mib.c` subdriver: support devices which report the shorter Vendor OID as their sysOID, e.g. "CyberPower PowerPanel Personal" [#1997] + and support more data points including hardware status alarms [#1982] - The `bestfortress` driver shutdown handling was fixed to use a non-trivial default timeout [#1820] From 8049ca38ee30f9262a113443565994c46cff1bf7 Mon Sep 17 00:00:00 2001 From: Tomasz bla Fortuna Date: Tue, 8 Aug 2023 16:13:29 +0200 Subject: [PATCH 0908/1232] drivers/nutdrv_qx.c: Support a quirk in Vultech V2000 UPS. This UPS seems to use null bytes within status bits. This might mean "unsupported". We will treat them as zeroes. Signed-off-by: Tomasz bla Fortuna --- drivers/nutdrv_qx.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index b1f236c663..9abaa1de3b 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1875,7 +1875,28 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) /* Copy bytes into the final buffer while detecting end of line - \r */ for (i = 0; i < bytes_available; i++) { + if (tmpbuf[i + 1] == 0x00 && bufpos == 0) { + /* Happens when a manually turned off UPS is connected to the USB */ + upsdebugx(3, "null byte read - is UPS off?"); + return 0; + } + + /* Vultech V2000 seems to use 0x00 within status bits. This might mean "unsupported". + * or something else completely. */ + if (tmpbuf[i + 1] == 0x00) { + if (bufpos >= 38) { + upsdebugx(3, "found null byte in status bits at %" PRIuSIZE " byte, assuming 0.", bufpos); + buf[bufpos++] = '0'; + continue; + } else { + upsdebugx(3, "found null byte in data stream - interrupting read."); + /* Break through two loops */ + goto end_of_message; + } + } + buf[bufpos++] = tmpbuf[i + 1]; + if (tmpbuf[i + 1] == 0x0d) { if (i + 1 != bytes_available) { upsdebugx(3, "trailing bytes in serial transmission found: %" PRIuSIZE " copied out of %" PRIuSIZE, @@ -1885,11 +1906,6 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) /* Break through two loops */ goto end_of_message; } - if (tmpbuf[i + 1] == 0x00) { - /* Happens when a manually turned off UPS is connected to the USB */ - upsdebugx(3, "null byte read - is UPS off?"); - return 0; - } } if (bytes_available <= 2) { From 7e6c76e83c7a974de0fea95a411726f98338fbbc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 13 Aug 2023 21:10:46 +0200 Subject: [PATCH 0909/1232] Revise doc changes about LISTEN * support per PR #2013 discussion Notably: * move from "would" to "will" verbiage; * specify IPv6 listening first, IPv4 next, as it goes in code; * lean towards trying to listen on two sockets separately always (unless the OS refuses to avoid IPv4-mapped IPv6 addressing). Signed-off-by: Jim Klimov --- NEWS | 11 +++++++---- UPGRADING | 16 ++++++++++------ conf/upsd.conf.sample | 21 +++++++++++---------- docs/config-notes.txt | 11 ++++++----- docs/man/upsd.conf.txt | 28 +++++++++++++++------------- docs/security.txt | 11 ++++++----- scripts/augeas/nutupsdconf.aug.in | 4 ++-- 7 files changed, 57 insertions(+), 45 deletions(-) diff --git a/NEWS b/NEWS index 1525607348..d7a9d571ac 100644 --- a/NEWS +++ b/NEWS @@ -284,14 +284,17 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - The `upsd` configured to listen on IPv6 addresses should handle only IPv6 (and not IPv4-mappings) to avoid surprises and insecurity; it - would warn if a hostname resolves to several addresses (and would only + will now warn if a host name resolves to several addresses (and will only listen on the first hit, as before in such cases) [#2012] - A definitive behavior for `LISTEN *` directives became specified, to try handling both IPv4 and IPv6 "any" address (subject to `upsd` CLI options - to only choose one, and to OS abilities); this use-case may be practically - implemented as a single IPv6 socket on systems with enabled "dual-stack" - support or as two separate listening sockets [#2012] + to only choose one, and to OS abilities). When both address families are + enabled, the `upsd` data server will first try to open an IPv6 socket + asking for disabled IPv4-mapped IPv6 address support (if the OS honors + that), and then an IPv4 socket (which may fail if the IPv6 socket already + covers it anyway); in other words, you can end up with one or two separate + listening sockets [#2012] - sstate (server state, e.g. upsd) should now "PING" drivers also if they last reported themselves as "stale" (and might later crash) so their diff --git a/UPGRADING b/UPGRADING index 7a92aae3d4..339ff59900 100644 --- a/UPGRADING +++ b/UPGRADING @@ -75,15 +75,19 @@ Changes from 2.8.0 to 2.8.1 IPv6 (and not IPv4-mappings like it might have done before) to avoid surprises and insecurity -- if user configurations somehow relied on this dual support, configuration changes may be needed to specify both - desired IP addresses. Note that the daemon logs would warn if a hostname - resolves to several addresses (and would only listen on the first hit, - as it did before in such cases) [#2012] + desired IP addresses. Note that the daemon logs will now warn if a + host name resolves to several addresses (and will only listen on the + first hit, as it did before in such cases) [#2012] - A definitive behavior for `LISTEN *` directives became specified, to try handling both IPv4 and IPv6 "any" address (subject to `upsd` CLI options - to only choose one, and to OS abilities); this use-case may be practically - implemented as a single IPv6 socket on systems with enabled "dual-stack" - support or as two separate listening sockets [#2012] + to only choose one, and to OS abilities). This use-case may be practically + implemented as a single IPv6 socket on systems with enabled and required + IPv4-mapped IPv6 address support, or as two separate listening sockets - + logged messages to this effect (e.g. inability to listen on IPv4 after + opening IPv6) are expected on some platforms. End-users may also want to + reconfigure their `upsd.conf` files to remove some now-redundant `LISTEN` + lines. [#2012] - Added support for `make sockdebug` for easier developer access to the tool; also if `configure --with-dev` is in effect, it would now be installed to diff --git a/conf/upsd.conf.sample b/conf/upsd.conf.sample index 29ed500127..277e58417f 100644 --- a/conf/upsd.conf.sample +++ b/conf/upsd.conf.sample @@ -64,11 +64,12 @@ # Note that it is not true for Windows platforms. You shouldn't use IPv6 in # your configuration files unless you have IPv6 installed. # -# As a special case, `LISTEN * ` (with an asterisk) would try -# to listen on "ANY" IP address for both IPv4 (0.0.0.0) and IPv6 (::0), -# subject to `upsd` command-line arguments or OS/kernel configuration. -# If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 -# then there would be one listening socket for both address types. +# As a special case, `LISTEN * ` (with an asterisk) will try +# to listen on "ANY" IP address for both IPv6 (::0) and IPv4 (0.0.0.0), +# subject to `upsd` command-line arguments, or system configuration. +# Note that if the system supports IPv4-mapped IPv6 addressing per RFC-3493, +# and does not allow to disable this mode, then there may be one listening +# socket to handle both address families. # # One or more LISTEN statements give the IP address (or name that # resolves to such an address) for upsd to listen on, optionally with @@ -81,11 +82,11 @@ # This will only be read at startup of upsd. If you make changes here, # you'll need to restart upsd, as reload will have no effect. # -# Please note that older NUT releases could have been using the "dual-stack" -# mode, if provided by the system. Current versions (since NUT v2.8.1 release) -# try to restrict their listening sockets to only support IPv6 addresses and -# so avoid IPv4-mapped mode, except when handling the special `LISTEN * ` -# directive. +# Please note that older NUT releases could have been using the IPv4-mapped +# IPv6 addressing (sometimes also known as "dual-stack") mode, if provided +# by the system. Current versions (since NUT v2.8.1 release) explicitly try +# to restrict their listening sockets to only support one address family on +# each socket, and so avoid IPv4-mapped mode where possible. # ======================================================================= # MAXCONN diff --git a/docs/config-notes.txt b/docs/config-notes.txt index ec24e1515f..8ed3269fd9 100644 --- a/docs/config-notes.txt +++ b/docs/config-notes.txt @@ -295,11 +295,12 @@ want `upsd` to listen on for connections, optionally with a port number. LISTEN 127.0.0.1 3493 LISTEN ::1 3493 -As a special case, `LISTEN * ` (with an asterisk) would try -to listen on "ANY" IP address for both IPv4 (`0.0.0.0`) and IPv6 (`::0`), -subject to `upsd` command-line arguments or OS/kernel configuration. -If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 -then there would be one listening socket for both address types. +As a special case, `LISTEN * ` (with an asterisk) will try to +listen on "ANY" IP address for both and IPv6 (`::0`) and IPv4 (`0.0.0.0`), +subject to `upsd` command-line arguments, or system configuration or support. +Note that if the system supports IPv4-mapped IPv6 addressing per RFC-3493, +and does not allow to disable this mode, then there may be one listening +socket to handle both address families. NOTE: Refer to the NUT user manual <> for information on how to access and secure upsd clients connections. diff --git a/docs/man/upsd.conf.txt b/docs/man/upsd.conf.txt index 57618b9b0b..af8582a700 100644 --- a/docs/man/upsd.conf.txt +++ b/docs/man/upsd.conf.txt @@ -66,15 +66,17 @@ compiled into the code. This overrides any value you may have set with upsd will listen on port 3493 for this interface. + Multiple LISTEN addresses may be specified. The default is to bind to -127.0.0.1 if no LISTEN addresses are specified (and ::1 if IPv6 support is -compiled in). +`127.0.0.1` if no LISTEN addresses are specified (and also `::1` if IPv6 +support is compiled in). + -To listen on all available interfaces, you may also use '0.0.0.0' for IPv4 and -and '::' for IPv6. As a special case, `LISTEN * ` (with an asterisk) -would try to listen on both IPv4 (`0.0.0.0`) and IPv6 (`::0`) wild-card IP -addresses, subject to `upsd` command-line arguments or OS/kernel configuration. -If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 -then there would be one listening socket for both address types. +To listen on all available interfaces and configured IP addresses of your +system, you may also use `::` for IPv6 and `0.0.0.0` for IPv4, respectively. +As a special case, a single `LISTEN * ` directive (with an asterisk) will +try to listen on both IPv6 (`::0`) and IPv4 (`0.0.0.0`) wild-card IP addresses, +subject to `upsd` command-line arguments or system configuration. +Note that if the system supports IPv4-mapped IPv6 addressing per RFC-3493, +and does not allow to disable this mode, then there may be one listening +socket to handle both address families. + LISTEN 127.0.0.1 LISTEN 192.168.50.1 @@ -85,11 +87,11 @@ then there would be one listening socket for both address types. This parameter will only be read at startup. You'll need to restart (rather than reload) upsd to apply any changes made here. + -Please note that older NUT releases could have been using the "dual-stack" -mode, if provided by the system. Current versions (since NUT v2.8.1 release) -try to restrict their listening sockets to only support IPv6 addresses and -so avoid IPv4-mapped mode, except when handling the special `LISTEN * ` -directive. +Please note that older NUT releases could have been using the IPv4-mapped +IPv6 addressing (sometimes also known as "dual-stack") mode, if provided +by the system. Current versions (since NUT v2.8.1 release) explicitly try +to restrict their listening sockets to only support one address family on +each socket, and so avoid IPv4-mapped mode where possible. "MAXCONN 'connections'":: diff --git a/docs/security.txt b/docs/security.txt index 7d69aa0bf3..a6594885fd 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -234,11 +234,12 @@ compiled in). LISTEN ::1 LISTEN 2001:0db8:1234:08d3:1319:8a2e:0370:7344 -As a special case, `LISTEN * ` (with an asterisk) would try -to listen on "ANY" IP address for both IPv4 (`0.0.0.0`) and IPv6 (`::0`), -subject to `upsd` command-line arguments or OS/kernel configuration. -If the system supports "dual-stack" mode (IPv4-mapped IPv6) per RFC-3493 -then there would be one listening socket for both address types. +As a special case, `LISTEN * ` (with an asterisk) will try to +listen on "ANY" IP address for both IPv6 (`::0`) and IPv4 (`0.0.0.0`), +subject to `upsd` command-line arguments, or system configuration or support. +Note that if the system supports IPv4-mapped IPv6 addressing per RFC-3493, +and does not allow to disable this mode, then there may be one listening +socket to handle both address families. This parameter will only be read at startup. You'll need to restart (rather than reload) `upsd` to apply any changes made here. diff --git a/scripts/augeas/nutupsdconf.aug.in b/scripts/augeas/nutupsdconf.aug.in index dff4fef435..1592048387 100644 --- a/scripts/augeas/nutupsdconf.aug.in +++ b/scripts/augeas/nutupsdconf.aug.in @@ -57,8 +57,8 @@ let upsd_certfile = [ opt_spc . key "CERTFILE" . sep_spc . store path . eol ] * LISTEN interface port * Multiple lines each with one LISTEN address (or host name) and an optional * port may be specified. The default is to bind to IPv4 and IPv6 "localhost" - * addresses (subject to CLI options `-4` or `-6` constraining IP version or - * OS kernel/configuration support), if no LISTEN addresses are specified. + * addresses (subject to CLI options `-4` or `-6` constraining IP version, + * or system configuration or support), if no LISTEN addresses are specified. * LISTEN 127.0.0.1 * LISTEN 192.168.50.1 * LISTEN ::1 From 7d04e37b1951b2c4a870122952adf44f47e8fad4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 13:45:14 +0200 Subject: [PATCH 0910/1232] server/upsd.c: simplify `LISTEN *` handling to not fiddle with optionality of `require_IPV6_V6ONLY` for one use-case [#2013 review, #2012] Signed-off-by: Jim Klimov --- server/upsd.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 3d1da59340..87a4ec3cf9 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -267,8 +267,6 @@ static void stype_free(stype_t *server) /* create a listening socket for tcp connections */ static void setuptcp(stype_t *server) { - /* Well, currently it is more a request than requirement... */ - static int require_IPV6_V6ONLY = 1; #ifdef WIN32 WSADATA WSAdata; WSAStartup(2,&WSAdata); @@ -306,10 +304,6 @@ static void setuptcp(stype_t *server) int canhaveAnyV4 = 0; int canhaveAnyV6 = 0; - /* For this use-case, we allow IPv6 to handle IPv4 if it can */ - int old_require_IPV6_V6ONLY = require_IPV6_V6ONLY; - require_IPV6_V6ONLY = (opt_af == AF_INET6); - /* Note: default opt_af==AF_UNSPEC so not constrained to only one protocol */ if (opt_af != AF_INET6) { /* Not constrained to IPv6 */ @@ -436,7 +430,6 @@ static void setuptcp(stype_t *server) } serverAnyV6 = NULL; - require_IPV6_V6ONLY = old_require_IPV6_V6ONLY; return; } @@ -467,16 +460,11 @@ static void setuptcp(stype_t *server) } /* Ordinarily we request that IPv6 listeners handle only IPv6 - * (except when we handle `LISTEN *` as detailed above). - * Note we specifically try to ensure this when CLI requires - * IPv6-only behavior (even if we want "any" addr for `LISTEN *`). + * and not IPv4 mapped addresses - if the OS would honour that. * TOTHINK: Does any platform need `#ifdef IPV6_V6ONLY` given * that we apparently already have AF_INET6 OS support everywhere? - * TOTHINK: Do we want to setsockopt() to explicitly allow dual-stack - * (perhaps counteracting OS default or customized configuration) - * when handling `LISTEN *` use-cases? */ - if (ai->ai_family == AF_INET6 && (require_IPV6_V6ONLY || (opt_af == AF_INET6))) { + if (ai->ai_family == AF_INET6) { if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one, sizeof(one)) != 0) { upsdebug_with_errno(3, "setuptcp: setsockopt IPV6_V6ONLY"); /* ack, ignore */ From a8b5896ab86e6e801766de4345f1c84407f7997f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:05:54 +0200 Subject: [PATCH 0911/1232] server/upsd.c: setuptcp(): drop commented-away optional sleep() [#2012] Signed-off-by: Jim Klimov --- server/upsd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 87a4ec3cf9..c11257135c 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -339,8 +339,6 @@ static void setuptcp(stype_t *server) canhaveAnyV4 = 1; close(serverAnyV4->sock_fd); serverAnyV4->sock_fd = ERROR_FD_SOCK; - /* Let the system know about the change: */ - /* usleep(100); */ } else { upsdebugx(3, "%s: Could not bind to %s:%s trying to handle a 'LISTEN *' directive", From af53ec5384433ceb07a5b45b5cc14d0bf6aaa572 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:16:24 +0200 Subject: [PATCH 0912/1232] server/upsd.c: setuptcp(): drop the trickery to get IPv4 first just to see if we can, then release it, then get IPv6 and then IPv4 again [#2013 review for #2012] Signed-off-by: Jim Klimov --- server/upsd.c | 56 +++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index c11257135c..c03da60f53 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -301,8 +301,7 @@ static void setuptcp(stype_t *server) */ if (!strcmp(server->addr, "*")) { stype_t *serverAnyV4 = NULL, *serverAnyV6 = NULL; - int canhaveAnyV4 = 0; - int canhaveAnyV6 = 0; + int canhaveAnyV4 = 0, canhaveAnyV6 = 0; /* Note: default opt_af==AF_UNSPEC so not constrained to only one protocol */ if (opt_af != AF_INET6) { @@ -327,26 +326,6 @@ static void setuptcp(stype_t *server) serverAnyV6->next = NULL; } - if (serverAnyV4) { - /* First pass to just check if we CAN have this listener now */ - setuptcp(serverAnyV4); - if (serverAnyV6) { - if (VALID_FD_SOCK(serverAnyV4->sock_fd)) { - upsdebugx(3, - "%s: Could bind to %s:%s trying to handle a 'LISTEN *' directive" - "; will release it for now to try IPv6", - __func__, serverAnyV4->addr, serverAnyV4->port); - canhaveAnyV4 = 1; - close(serverAnyV4->sock_fd); - serverAnyV4->sock_fd = ERROR_FD_SOCK; - } else { - upsdebugx(3, - "%s: Could not bind to %s:%s trying to handle a 'LISTEN *' directive", - __func__, serverAnyV4->addr, serverAnyV4->port); - } - } /* else: just keep it, all done */ - } - if (serverAnyV6) { setuptcp(serverAnyV6); if (VALID_FD_SOCK(serverAnyV6->sock_fd)) { @@ -356,20 +335,27 @@ static void setuptcp(stype_t *server) "%s: Could not bind to %s:%s trying to handle a 'LISTEN *' directive", __func__, serverAnyV6->addr, serverAnyV6->port); } + } - if (serverAnyV4 && canhaveAnyV4) { - /* Second pass to get this listener if we can (no IPv4-mapped IPv6 - * support was in force on this platform or its configuration) */ - upsdebugx(3, "%s: try taking IPv4 'ANY' again " - "(if dual-stack IPv6 'ANY' did not grab it)", __func__); - setuptcp(serverAnyV4); - if (INVALID_FD_SOCK(serverAnyV4->sock_fd)) { - upsdebugx(3, - "%s: Could not bind to IPv4 %s:%s after trying to bind to IPv6: " - "assuming dual-stack support on this system", - __func__, serverAnyV4->addr, serverAnyV4->port); - canhaveAnyV4 = 0; - } + if (serverAnyV4) { + /* Try to get this listener if we can (no IPv4-mapped + * IPv6 support was in force on this platform or its + * configuration in some way that setsockopt(IPV6_V6ONLY) + * failed to cancel). + */ + upsdebugx(3, "%s: try taking IPv4 'ANY'%s", + __func__, + serverAnyV6 ? " (if dual-stack IPv6 'ANY' did not grab it)" : ""); + setuptcp(serverAnyV4); + if (VALID_FD_SOCK(serverAnyV4->sock_fd)) { + canhaveAnyV4 = 1; + } else { + upsdebugx(3, + "%s: Could not bind to IPv4 %s:%s%s", + __func__, serverAnyV4->addr, serverAnyV4->port, + serverAnyV6 ? (" after trying to bind to IPv6: " + "assuming dual-stack support on this " + "system could not be disabled") : ""); } } From dec2488d8de8332290f2ec3d24280ac07c747b24 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:33:47 +0200 Subject: [PATCH 0913/1232] NEWS, UPGRADING: finish full sentences with a period [#2012] Signed-off-by: Jim Klimov --- NEWS | 2 +- UPGRADING | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index d7a9d571ac..fe8dff5db1 100644 --- a/NEWS +++ b/NEWS @@ -294,7 +294,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. asking for disabled IPv4-mapped IPv6 address support (if the OS honors that), and then an IPv4 socket (which may fail if the IPv6 socket already covers it anyway); in other words, you can end up with one or two separate - listening sockets [#2012] + listening sockets. [#2012] - sstate (server state, e.g. upsd) should now "PING" drivers also if they last reported themselves as "stale" (and might later crash) so their diff --git a/UPGRADING b/UPGRADING index 339ff59900..d29edea18b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -77,7 +77,7 @@ Changes from 2.8.0 to 2.8.1 this dual support, configuration changes may be needed to specify both desired IP addresses. Note that the daemon logs will now warn if a host name resolves to several addresses (and will only listen on the - first hit, as it did before in such cases) [#2012] + first hit, as it did before in such cases). [#2012] - A definitive behavior for `LISTEN *` directives became specified, to try handling both IPv4 and IPv6 "any" address (subject to `upsd` CLI options From df7961be6909c09dd70763fd041ccb86e02d5f73 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:39:33 +0200 Subject: [PATCH 0914/1232] configure.ac: explicitly check for inet_ntop() support along with both AF_INET and AF_INET6 (we have IPv4 and IPv6 capability everywhere, right?) [#2012] Signed-off-by: Jim Klimov --- configure.ac | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index f32de9e8b0..b438855634 100644 --- a/configure.ac +++ b/configure.ac @@ -1120,7 +1120,7 @@ NUT_TYPE_SOCKLEN_T NUT_CHECK_SOCKETLIB NUT_FUNC_GETNAMEINFO_ARGTYPES -AC_CACHE_CHECK([for inet_ntop()], +AC_CACHE_CHECK([for inet_ntop() with IPv4 and IPv6 support], [ac_cv_func_inet_ntop], [AC_LANG_PUSH([C]) dnl e.g. add "-lws2_32" for mingw builds @@ -1148,7 +1148,8 @@ AC_CACHE_CHECK([for inet_ntop()], ]], [[/* const char* inet_ntop(int af, const void* src, char* dst, size_t cnt); */ char buf[128]; -printf("%s", inet_ntop(AF_INET, "1.2.3.4", buf, 10)) +printf("%s", inet_ntop(AF_INET, "1.2.3.4", buf, 10)); +printf("%s", inet_ntop(AF_INET6, "::1", buf, 10)) /* autoconf adds ";return 0;" */ ]])], [ac_cv_func_inet_ntop=yes], [ac_cv_func_inet_ntop=no] From 8daab44213f97153296fde29c364f11f407abfd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:49:17 +0200 Subject: [PATCH 0915/1232] server/upsd.c: setuptcp(): update big comment about "LISTEN *" nuances to match current logic; drop GitHub reference [#2013 review for #2012] Signed-off-by: Jim Klimov --- server/upsd.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index c03da60f53..91419fc72c 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -285,19 +285,23 @@ static void setuptcp(stype_t *server) upsdebugx(3, "setuptcp: try to bind to %s port %s", server->addr, server->port); - /* Special handling for `LISTEN * ` directive with literal asterisk: - * on systems with RFC-3493 (no relation!) support for "IPv4-mapped addresses" - * it suffices to LISTEN on "::" (aka "::0" or "0:0:0:0:0:0:0:0") and also - * get an IPv4 any-address listener. More so, they would conflict and - * listening on one such socket precludes listening on the other. On other - * systems (or with disabled mapping so IPv6 means IPv6 only) we need both. - * So we jump through some hoops: - * * Try to get IPv4 any-address, just to know if it is available right now; - * * Free it and try to get IPv6 any-address, and try to get again that - * IPv4 any-address (IFF it was available before but is not available now - - * not a problem). - * * Remember the entries used, to release later. - * For more details see https://github.com/networkupstools/nut/issues/2012 + /* Special handling note for `LISTEN * ` directive with the + * literal asterisk on systems with RFC-3493 (no relation!) support + * for "IPv4-mapped addresses": it is possible (and technically + * suffices) to LISTEN on "::" (aka "::0" or "0:0:0:0:0:0:0:0") and + * also get an IPv4 any-address listener automatically. More so, + * they would conflict and listening on one such socket precludes + * listening on the other. On other systems (or with disabled + * mapping so IPv6 really means "IPv6 only") we need both sockets. + * NUT asks the system for "IPv6 only" mode when listening on any + * sort of IPv6 addresses; it is however up to the system to implement + * that ability and comply with our request. + * Here we jump through some hoops: + * * Try to get IPv6 any-address (unless constrained by CLI to IPv4); + * * Try to get IPv4 any-address (unless constrained by CLI to IPv6), + * log information for the sysadmin that it might conflict with the + * IPv6 listener (IFF we have just opened one); + * * Remember the one or two linked-list entries used, to release later. */ if (!strcmp(server->addr, "*")) { stype_t *serverAnyV4 = NULL, *serverAnyV6 = NULL; From b0c97f71c7eaf8dac358396277fafcc6ba77c3d9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 14 Aug 2023 14:50:41 +0200 Subject: [PATCH 0916/1232] server/upsd.c: setuptcp(): when informing about possible IPv6/IPv4 "ANY" address listener conflict, consult actual state in "canhaveAnyV6" and not the possibility via "serverAnyV6!=null" [#2013] 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 91419fc72c..7123d625d6 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -349,7 +349,7 @@ static void setuptcp(stype_t *server) */ upsdebugx(3, "%s: try taking IPv4 'ANY'%s", __func__, - serverAnyV6 ? " (if dual-stack IPv6 'ANY' did not grab it)" : ""); + canhaveAnyV6 ? " (if dual-stack IPv6 'ANY' did not grab it)" : ""); setuptcp(serverAnyV4); if (VALID_FD_SOCK(serverAnyV4->sock_fd)) { canhaveAnyV4 = 1; @@ -357,7 +357,7 @@ static void setuptcp(stype_t *server) upsdebugx(3, "%s: Could not bind to IPv4 %s:%s%s", __func__, serverAnyV4->addr, serverAnyV4->port, - serverAnyV6 ? (" after trying to bind to IPv6: " + canhaveAnyV6 ? (" after trying to bind to IPv6: " "assuming dual-stack support on this " "system could not be disabled") : ""); } From 1555fb7949ae6059a69928dab0c05bdab8d71a44 Mon Sep 17 00:00:00 2001 From: Tomasz Fortuna Date: Sun, 13 Aug 2023 09:27:12 +0200 Subject: [PATCH 0917/1232] drivers/nutdrv_qx.c: Add documentation file. Document various possible transmissions. Might be required to construct testcases one day - adding new UPS shouldn't cause regressions in older ones. Signed-off-by: Tomasz Fortuna --- NEWS | 3 +- docs/nut.dict | 1 + docs/nutdrv_qx-subdrivers.txt | 170 ++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8cf46b9413..72dc477fb7 100644 --- a/NEWS +++ b/NEWS @@ -100,7 +100,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * the `voltronic_qs_protocol` should now accept both "V" (as before) and newly "H" dialects, which otherwise seem interchangeable [#1623] * the `armac` subdriver was enhanced to support devices with a different - response pattern than previously expected per initial contribution [#1978] + response pattern than previously expected per initial contribution. + It was tested to work with Vultech V2000 and Armac PF1 series. [#1978] - usbhid-ups updates: * cps-hid subdriver now applies same report descriptor fixing logic to diff --git a/docs/nut.dict b/docs/nut.dict index 21f5195b53..d712e5ba24 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -3195,3 +3195,4 @@ zwfa zzz Åstrand Ørpetveit +Vultech diff --git a/docs/nutdrv_qx-subdrivers.txt b/docs/nutdrv_qx-subdrivers.txt index 8d786450b9..31dba9964d 100644 --- a/docs/nutdrv_qx-subdrivers.txt +++ b/docs/nutdrv_qx-subdrivers.txt @@ -960,6 +960,176 @@ Return the currently processed status so that it can be checked with one of the If you need to edit the current status call this function with one of the NUT status (all but +OB+ are supported, simply set it as not +OL+); prefix them with an exclamation mark if you want to clear them from the status (e.g. +!OL+). +Armac Subdriver +~~~~~~~~~~~~~~~ + +Armac subdriver is based on reverse engineering of Power Manager II software by +Richcomm Technologies writen in 2005 that is still (as of 2023) being +distributed as a valid software for freshly sold UPS of various manufacturers. +It uses commands as defined for Megatec protocol - but has a different +communication mechanism. + +It uses two types of USB interrupt transfers: +- 4 bytes to send a command (usually single transfer). +- 6 byte chunk to read a reply (multiple transfers). + +Transfers are similar to those of the richcomm nut driver, but the transferred +data is not short binary commands. Instead, serial text data is overlayed in +these transfers in a way that creates a badly made USB serial interface. UPS +reply looks similar to this: + + 0 1 2 3 4 5 +HL 00 00 00 00 00 + +HL is a control byte. Its high nibble meaning is unknown. It changes between +two possible values during transmission. Low nibble encodes number of bytes +that have a meaning in the transaction. For example there are 5 bytes that +might contain ASCII serial data, but only some might be valid, and other might +be random, stale buffer data, etc. + +What follows is set of observed transmissions by various UPSes gathered from +Github issues. + +Transfer dumps +^^^^^^^^^^^^^^ + +#### Vultech V2000 + +---- +419.987514 [D4] armac command Q1 +419.988307 [D4] armac cleanup ret i=0 ret=6 ctrl=c0 +420.119402 [D4] read: ret 6 buf 81: 28 30 31 30 30 >(0100< +420.130383 [D4] read: ret 6 buf c1: 32 30 31 30 30 >20100< +420.141408 [D4] read: ret 6 buf 82: 33 33 31 30 30 >33100< +420.152201 [D4] read: ret 6 buf c3: 2e 30 20 30 30 >.0 00< +420.153237 [D4] read: ret 6 buf 82: 30 30 20 30 30 >00 00< +420.164299 [D4] read: ret 6 buf c1: 30 30 20 30 30 >00 00< +420.175293 [D4] read: ret 6 buf 82: 2e 30 20 30 30 >.0 00< +420.186358 [D4] read: ret 6 buf c3: 20 32 33 30 30 > 2300< +420.190322 [D4] read: ret 6 buf 83: 33 2e 30 30 30 >3.000< +420.194323 [D4] read: ret 6 buf c1: 20 2e 30 30 30 > .000< +420.205358 [D4] read: ret 6 buf 81: 30 2e 30 30 30 >0.000< +420.216318 [D4] read: ret 6 buf c2: 31 34 30 30 30 >14000< +420.227445 [D4] read: ret 6 buf 83: 20 34 39 30 30 > 4900< +420.228334 [D4] read: ret 6 buf c2: 2e 30 39 30 30 >.0900< +420.239461 [D4] read: ret 6 buf 81: 20 30 39 30 30 > 0900< +420.250411 [D4] read: ret 6 buf c2: 32 37 39 30 30 >27900< +420.261405 [D4] read: ret 6 buf 83: 2e 30 20 30 30 >.0 00< +420.265468 [D4] read: ret 6 buf c3: 32 30 2e 30 30 >20.00< +420.269465 [D4] read: ret 6 buf 81: 38 30 2e 30 30 >80.00< +420.280322 [D4] read: ret 6 buf c1: 20 30 2e 30 30 > 0.00< +420.291469 [D4] read: ret 6 buf 82: 30 30 2e 30 30 >00.00< +420.302465 [D4] read: ret 6 buf c3: 30 30 31 30 30 >00100< +420.303511 [D4] read: ret 6 buf 82: 00 30 31 30 30 > <- This has 0x00 and '0', will be read as "00" +420.303515 [D3] found null byte in status bits at 43 byte, assuming 0. +420.314425 [D4] read: ret 6 buf c1: 31 30 31 30 30 >10100< <- this has '1' +420.325432 [D4] read: ret 6 buf 81: 0d 30 31 30 30 >.0100< <- and this finishes with `\r`. +420.325442 [D3] armac command Q1 response read: '(233.0 000.0 233.0 014 49.0 27.0 20.8 00001001' +---- + +---- +1.185164 [D4] armac command ID +1.316257 [D4] read: ret 6 buf c1: 23 31 00 30 30 >#1 +1.327309 [D4] read: ret 6 buf 81: 20 31 00 30 30 > 1 +1.338264 [D4] read: ret 6 buf c2: 20 20 00 30 30 > +1.349151 [D4] read: ret 6 buf 83: 20 20 20 30 30 > 00< +1.360277 [D4] read: ret 6 buf c2: 20 20 20 30 30 > 00< +1.371322 [D4] read: ret 6 buf 83: 20 20 20 30 30 > 00< +1.382265 [D4] read: ret 6 buf c3: 20 20 20 30 30 > 00< +1.393156 [D4] read: ret 6 buf 82: 20 20 20 30 30 > 00< +1.404324 [D4] read: ret 6 buf c3: 20 20 20 30 30 > 00< +1.415342 [D4] read: ret 6 buf 83: 20 20 20 30 30 > 00< +1.426292 [D4] read: ret 6 buf c2: 20 20 20 30 30 > 00< +1.437203 [D4] read: ret 6 buf 83: 20 20 20 30 30 > 00< +1.448328 [D4] read: ret 6 buf c3: 56 34 2e 30 30 >V4.00< +1.459293 [D4] read: ret 6 buf 82: 31 30 2e 30 30 >10.00< +1.470274 [D4] read: ret 6 buf c3: 20 20 20 30 30 > 00< +1.481208 [D4] read: ret 6 buf 82: 20 20 20 30 30 > 00< +1.492261 [D4] read: ret 6 buf c1: 0d 20 20 30 30 > +1.492270 [D3] armac command ID response read: '# V4.10 ' +---- + +---- +4.749667 [D4] armac command F +4.876638 [D4] read: ret 6 buf 81: 23 31 00 30 30 >#1 +4.887614 [D4] read: ret 6 buf c1: 32 31 00 30 30 >21 +4.898644 [D4] read: ret 6 buf 82: 32 30 00 30 30 >20 +4.909595 [D4] read: ret 6 buf c3: 2e 30 20 30 30 >.0 00< +4.920648 [D4] read: ret 6 buf 82: 30 30 20 30 30 >00 00< +4.931629 [D4] read: ret 6 buf c3: 35 20 32 30 30 >5 200< +4.942601 [D4] read: ret 6 buf 83: 34 2e 30 30 30 >4.000< +4.953666 [D4] read: ret 6 buf c2: 30 20 30 30 30 >0 000< +4.964535 [D4] read: ret 6 buf 83: 35 30 2e 30 30 >50.00< +4.975540 [D4] read: ret 6 buf c2: 30 0d 2e 30 30 >0 +4.975546 [D3] armac command F response read: '#220.0 005 24.00 50.0' +---- + +#### Armac R/2000I/PSW + +---- +112.966856 [D4] armac command Q1 +112.968197 [D4] armac cleanup ret i=0 ret=6 ctrl=c0 <- Cleanups required. +113.091193 [D4] read: ret 6 buf 81: 28 30 0d 2e 30 >(0 <- Usually 1-3 bytes available in transfer. +113.103211 [D4] read: ret 6 buf c1: 30 30 0d 2e 30 >00 +113.115180 [D4] read: ret 6 buf 82: 30 30 0d 2e 30 >00 +113.117144 [D4] read: ret 6 buf c3: 2e 30 20 2e 30 >.0 .0< +113.120150 [D4] read: ret 6 buf 81: 31 30 20 2e 30 >10 .0< +113.132178 [D4] read: ret 6 buf c1: 34 30 20 2e 30 >40 .0< +113.144159 [D4] read: ret 6 buf 82: 30 2e 20 2e 30 >0. .0< +113.146149 [D4] read: ret 6 buf c3: 30 20 32 2e 30 >0 2.0< +113.149173 [D4] read: ret 6 buf 81: 32 20 32 2e 30 >2 2.0< +113.161167 [D4] read: ret 6 buf c1: 37 20 32 2e 30 >7 2.0< +113.173159 [D4] read: ret 6 buf 82: 2e 30 32 2e 30 >.02.0< +113.175157 [D4] read: ret 6 buf c3: 20 30 30 2e 30 > 00.0< +113.178158 [D4] read: ret 6 buf 81: 32 30 30 2e 30 >200.0< +113.190157 [D4] read: ret 6 buf c1: 20 30 30 2e 30 > 00.0< +113.202161 [D4] read: ret 6 buf 82: 30 30 30 2e 30 >000.0< +113.204154 [D4] read: ret 6 buf c3: 2e 30 20 2e 30 >.0 .0< +113.207150 [D4] read: ret 6 buf 81: 34 30 20 2e 30 >40 .0< +113.219174 [D4] read: ret 6 buf c1: 36 30 20 2e 30 >60 .0< +113.231165 [D4] read: ret 6 buf 82: 2e 38 20 2e 30 >.8 .0< +113.233157 [D4] read: ret 6 buf c3: 20 35 36 2e 30 > 56.0< +113.237149 [D4] read: ret 6 buf 81: 2e 35 36 2e 30 >.56.0< +113.249168 [D4] read: ret 6 buf c1: 30 35 36 2e 30 >056.0< +113.261155 [D4] read: ret 6 buf 83: 20 31 30 2e 30 > 10.0< +113.263151 [D4] read: ret 6 buf c2: 30 30 30 2e 30 >000.0< +113.266152 [D4] read: ret 6 buf 81: 31 30 30 2e 30 >100.0< +113.278161 [D4] read: ret 6 buf c1: 30 30 30 2e 30 >000.0< <- No Null bytes. +113.290155 [D4] read: ret 6 buf 82: 30 30 30 2e 30 >000.0< +113.292159 [D4] read: ret 6 buf c1: 0d 30 30 2e 30 > +113.292169 [D3] armac command Q1 response read: '(000.0 140.0 227.0 002 00.0 46.8 56.0 10001000' +---- + +Next query would return 0x80 control byte - 0 available bytes. This used to +terminate transmission, but some UPS don't work like that. + + +#### Armac R/3000I/PF1 + +---- +0.083301 [D4] armac command Q1 +0.164847 [D4] read: ret 6 buf a6: 28 32 34 31 2e >(241.< +0.184839 [D4] read: ret 6 buf 86: 35 20 30 30 30 >5 000< +0.205851 [D4] read: ret 6 buf a6: 2e 30 20 32 33 >.0 23< +0.226849 [D4] read: ret 6 buf 86: 30 2e 33 20 30 >0.3 0< +0.247859 [D4] read: ret 6 buf a6: 30 30 20 34 39 >00 49< +0.268862 [D4] read: ret 6 buf 86: 2e 39 20 32 2e >.9 2.< +0.289857 [D4] read: ret 6 buf a6: 32 35 20 34 38 >25 48< +0.309866 [D4] read: ret 6 buf 86: 2e 30 20 30 30 >.0 00< +0.330863 [D4] read: ret 6 buf a6: 30 30 30 30 30 >00000< +0.827913 [D4] read: ret 6 buf 83: 31 0d 30 30 30 >1 000< +0.827927 [D3] armac command Q1 response read: '(241.5 000.0 230.3 000 49.9 2.25 48.0 00000001' +0.827954 [D4] armac command ID +1.394985 [D4] read: ret 6 buf a5: 4e 41 4b 0d 30 >NAK < +1.395001 [D3] armac command ID response read: 'NAK' +---- + +This UPS sends higher nibble set to 6 often, which exceeds available bytes. +Maybe means that more are available. Its serial-USB bridge is probably faster. +We read 5 bytes in case 6 nibble is sent. End of transmission is marked by `\r`, +no 0 nibble is sent. + + Notes ~~~~~ From 566da82636501e8f1b4ad64b8980ff417455b32f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 17 Aug 2023 01:06:40 +0200 Subject: [PATCH 0918/1232] docs/nutdrv_qx-subdrivers.txt, docs/nut.dict: fix some typos and update the dictionary [#2005] Signed-off-by: Jim Klimov --- docs/nut.dict | 9 +++++---- docs/nutdrv_qx-subdrivers.txt | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/nut.dict b/docs/nut.dict index d712e5ba24..028feaaea8 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3196 utf-8 +personal_ws-1.1 en 3198 utf-8 AAS ABI ACFAIL @@ -449,6 +449,7 @@ HFILE HIDIOCINITREPORT HIDRDD HITRANS +HL HMAC HNX HOMEBREW @@ -1365,6 +1366,7 @@ Viewsonic Viktor VirCIO Vout +Vultech Václav WALKMODE WARNFATAL @@ -1613,8 +1615,8 @@ bsd bsv bt bti -btnG btn +btnG btt buckboosthyst buckvolts @@ -2649,10 +2651,10 @@ qx's qxflags rD rackmount +raquo raritan ratedva ratedwatts -raquo rb rcctl readline @@ -3195,4 +3197,3 @@ zwfa zzz Åstrand Ørpetveit -Vultech diff --git a/docs/nutdrv_qx-subdrivers.txt b/docs/nutdrv_qx-subdrivers.txt index 31dba9964d..bc0dde9a61 100644 --- a/docs/nutdrv_qx-subdrivers.txt +++ b/docs/nutdrv_qx-subdrivers.txt @@ -964,7 +964,7 @@ Armac Subdriver ~~~~~~~~~~~~~~~ Armac subdriver is based on reverse engineering of Power Manager II software by -Richcomm Technologies writen in 2005 that is still (as of 2023) being +Richcomm Technologies written in 2005 that is still (as of 2023) being distributed as a valid software for freshly sold UPS of various manufacturers. It uses commands as defined for Megatec protocol - but has a different communication mechanism. @@ -974,7 +974,7 @@ It uses two types of USB interrupt transfers: - 6 byte chunk to read a reply (multiple transfers). Transfers are similar to those of the richcomm nut driver, but the transferred -data is not short binary commands. Instead, serial text data is overlayed in +data is not short binary commands. Instead, serial text data is overlaid in these transfers in a way that creates a badly made USB serial interface. UPS reply looks similar to this: From 42f121a96837f609b8e3af55ee83c5d7cae69242 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 13:28:38 +0200 Subject: [PATCH 0919/1232] A few cosmetic fixes (typos, indents...) Signed-off-by: Jim Klimov --- drivers/hidparser.c | 4 ++-- drivers/mge-hid.c | 10 ++++++---- drivers/usbhid-ups.c | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/hidparser.c b/drivers/hidparser.c index 0d7b53f80e..d77734eb9f 100644 --- a/drivers/hidparser.c +++ b/drivers/hidparser.c @@ -202,7 +202,7 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData) /* Remove Usage */ pParser->UsageSize--; - } + } /* Get Index if any */ if (pParser->Value >= 0x80) { @@ -361,7 +361,7 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData) upslogx(LOG_ERR, "%s: HID Usage too high", __func__); /* FIXME: comparison is always false due to limited range of data type [-Werror=type-limits] - * with ReportID beint uint8_t and MAX_REPORT being 500 currently */ + * with ReportID being uint8_t and MAX_REPORT being 500 currently */ /* if(pParser->Data.ReportID >= MAX_REPORT) upslogx(LOG_ERR, "%s: Too many HID reports", __func__); diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 3b152f374b..1a20ac9968 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -169,12 +169,12 @@ static char mge_scratch_buf[20]; * float mode is not important from the software's perspective, it's there to * help determine if the charger is advancing correctly. * So in float mode, the charger is charging the battery, so by definition you - * can assert the CHRG flag in NUT when in “float” mode or “charge” mode. - * When in “rest” mode the charger is not delivering anything to the battery, + * can assert the CHRG flag in NUT when in "float" mode or "charge" mode. + * When in "rest" mode the charger is not delivering anything to the battery, * but it will when the ABM cycle(28 days) ends, or a battery discharge occurs - * and utility returns. This is when the ABM status should be “resting”. + * and utility returns. This is when the ABM status should be "resting". * If a battery failure is detected that disables the charger, it should be - * reporting “off” in the ABM charger status. + * reporting "off" in the ABM charger status. * Of course when delivering load power from the battery, the ABM status is * discharging. */ @@ -1271,6 +1271,7 @@ static hid_info_t mge_hid2nut[] = { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, { "BOOL", 0, 0, "UPS.PowerConverter.Input.[3].PresentStatus.Used", NULL, NULL, 0, mge_onbatt_info }, #if 0 + /* NOTE: see entry with eaton_converter_online_info below now */ { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Used", NULL, NULL, 0, online_info }, #endif /* These 2 ones are used when ABM is disabled */ @@ -1298,6 +1299,7 @@ static hid_info_t mge_hid2nut[] = * and must hence be after "UPS.PowerSummary.PresentStatus.Good" */ { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Used", NULL, NULL, 0, eaton_converter_online_info }, { "BOOL", 0, 0, "UPS.PowerConverter.Input.[2].PresentStatus.Used", NULL, NULL, 0, bypass_auto_info }, /* Automatic bypass */ + /* NOTE: entry [3] is above as mge_onbatt_info */ { "BOOL", 0, 0, "UPS.PowerConverter.Input.[4].PresentStatus.Used", NULL, NULL, 0, bypass_manual_info }, /* Manual bypass */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FanFailure", NULL, NULL, 0, fanfail_info }, { "BOOL", 0, 0, "UPS.BatterySystem.Battery.PresentStatus.Present", NULL, NULL, 0, nobattery_info }, diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 3a8cc7120a..50220e097e 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -820,7 +820,7 @@ void upsdrv_makevartable(void) #else addvar(VAR_VALUE, "notification", - "Set notification type, (ignored, only for backward compatibility)"); + "Set notification type (ignored, only for backward compatibility)"); #endif } From d863555e100a8b199cab312e179e0c06965f8395 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 13:30:11 +0200 Subject: [PATCH 0920/1232] Reword "#if(n)def SHUT_MODE" clauses, comment their "#else/#endif" parts [#2022] Signed-off-by: Jim Klimov --- drivers/hidparser.h | 6 ++--- drivers/libhid.c | 18 ++++++------- drivers/libhid.h | 6 ++--- drivers/mge-hid.c | 14 +++++----- drivers/usbhid-ups.c | 64 +++++++++++++++++++++++--------------------- 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/drivers/hidparser.h b/drivers/hidparser.h index 1a2a3a7045..07b9f267aa 100644 --- a/drivers/hidparser.h +++ b/drivers/hidparser.h @@ -38,11 +38,11 @@ extern "C" { /* Include "usb-common.h" or "libshut.h" as appropriate, to define the * usb_ctrl_* types used below according to the backend USB API version */ -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE # include "libshut.h" -#else +#else /* !SHUT_MODE => USB */ # include "usb-common.h" -#endif +#endif /* SHUT_MODE / USB */ /* * Parse_ReportDesc diff --git a/drivers/libhid.c b/drivers/libhid.c index 3999feca46..a7acdd880a 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -46,13 +46,13 @@ #include "nut_stdint.h" /* Communication layers and drivers (USB and MGE SHUT) */ -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE #include "libshut.h" communication_subdriver_t *comm_driver = &shut_subdriver; -#else +#else /* !SHUT_MODE => USB */ #include "nut_libusb.h" communication_subdriver_t *comm_driver = &usb_subdriver; -#endif +#endif /* SHUT_MODE / USB */ /* support functions */ static double logical_to_physical(HIDData_t *Data, long logical); @@ -405,13 +405,13 @@ static struct { void HIDDumpTree(hid_dev_handle_t udev, HIDDevice_t *hd, usage_tables_t *utab) { size_t i; -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE NUT_UNUSED_VARIABLE(hd); -#else +#else /* !SHUT_MODE => USB */ /* extract the VendorId for further testing */ int vendorID = hd->VendorID; int productID = hd->ProductID; -#endif +#endif /* SHUT_MODE / USB */ /* Do not go further if we already know nothing will be displayed. * Some reports take a while before they timeout, so if these are @@ -430,11 +430,11 @@ void HIDDumpTree(hid_dev_handle_t udev, HIDDevice_t *hd, usage_tables_t *utab) HIDData_t *pData = &pDesc->item[i]; /* skip reports 254/255 for Eaton / MGE / Dell due to special handling needs */ -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE if ((pData->ReportID == 254) || (pData->ReportID == 255)) { continue; } -#else +#else /* !SHUT_MODE => USB */ if ((vendorID == 0x0463) || (vendorID == 0x047c)) { if ((pData->ReportID == 254) || (pData->ReportID == 255)) { continue; @@ -447,7 +447,7 @@ void HIDDumpTree(hid_dev_handle_t udev, HIDDevice_t *hd, usage_tables_t *utab) continue; } } -#endif +#endif /* SHUT_MODE / USB */ /* Get data value */ if (HIDGetDataValue(udev, pData, &value, MAX_TS) == 1) { diff --git a/drivers/libhid.h b/drivers/libhid.h index b0aea331b0..613fda9aae 100644 --- a/drivers/libhid.h +++ b/drivers/libhid.h @@ -37,21 +37,21 @@ #include "timehead.h" -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE #include "libshut.h" typedef SHUTDevice_t HIDDevice_t; typedef char HIDDeviceMatcher_t; typedef usb_dev_handle hid_dev_handle_t; typedef shut_communication_subdriver_t communication_subdriver_t; #define HID_DEV_HANDLE_CLOSED (hid_dev_handle_t)(ERROR_FD_SER) -#else +#else /* !SHUT_MODE => USB */ #include "nut_libusb.h" /* includes usb-common.h */ typedef USBDevice_t HIDDevice_t; typedef USBDeviceMatcher_t HIDDeviceMatcher_t; typedef usb_dev_handle * hid_dev_handle_t; typedef usb_communication_subdriver_t communication_subdriver_t; #define HID_DEV_HANDLE_CLOSED (hid_dev_handle_t)(NULL) -#endif +#endif /* SHUT_MODE / USB */ /* use explicit booleans */ #ifndef FALSE diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 1a20ac9968..ba5dbc2ef0 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -65,7 +65,7 @@ /* IBM */ #define IBM_VENDORID 0x04b3 -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) #include "usb-common.h" /* USB IDs device table */ @@ -98,7 +98,7 @@ static usb_device_id_t mge_usb_device_table[] = { /* Terminating entry */ { 0, 0, NULL } }; -#endif +#endif /* !SHUT_MODE => USB */ typedef enum { MGE_DEFAULT_OFFLINE = 0, @@ -1574,7 +1574,10 @@ static const char *mge_format_serial(HIDDevice_t *hd) { * the device is supported by this subdriver, else 0. */ static int mge_claim(HIDDevice_t *hd) { -#ifndef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE + NUT_UNUSED_VARIABLE(hd); + return 1; +#else /* !SHUT_MODE => USB */ int status = is_usb_device_supported(mge_usb_device_table, hd); switch (status) { @@ -1641,10 +1644,7 @@ static int mge_claim(HIDDevice_t *hd) { default: return 0; } -#else - NUT_UNUSED_VARIABLE(hd); - return 1; -#endif +#endif /* SHUT_MODE / USB */ } subdriver_t mge_subdriver = { diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 50220e097e..011703d63f 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -45,7 +45,7 @@ /* include all known subdrivers */ #include "mge-hid.h" -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) /* explore stub goes first, others alphabetically */ #include "explore-hid.h" #include "apc-hid.h" @@ -62,15 +62,16 @@ #include "powervar-hid.h" #include "salicru-hid.h" #include "tripplite-hid.h" -#endif +#endif /* !SHUT_MODE => USB */ /* Reference list of available subdrivers */ static subdriver_t *subdriver_list[] = { -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) &explore_subdriver, -#endif +#endif /* !SHUT_MODE => USB */ + /* mge-hid.c supports both SHUT and USB */ &mge_subdriver, -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) &apc_subdriver, &arduino_subdriver, &belkin_subdriver, @@ -85,7 +86,7 @@ static subdriver_t *subdriver_list[] = { &powervar_subdriver, &salicru_subdriver, &tripplite_subdriver, -#endif +#endif /* !SHUT_MODE => USB */ NULL }; @@ -97,11 +98,11 @@ upsdrv_info_t upsdrv_info = { "Arjen de Korte \n" \ "John Stamp ", /*FIXME: link the subdrivers? do the same as for the mibs! */ -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) DRV_STABLE, -#else +#else /* SHUT_MODE */ DRV_EXPERIMENTAL, -#endif +#endif /* SHUT_MODE / USB */ { &comm_upsdrv_info, NULL } }; @@ -119,10 +120,10 @@ static subdriver_t *subdriver = NULL; static HIDDevice_t *hd = NULL; static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, 0, NULL }; static HIDDeviceMatcher_t *subdriver_matcher = NULL; -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) static HIDDeviceMatcher_t *exact_matcher = NULL; static HIDDeviceMatcher_t *regex_matcher = NULL; -#endif +#endif /* !SHUT_MODE => USB */ static int pollfreq = DEFAULT_POLLFREQ; static unsigned ups_status = 0; static bool_t data_has_changed = FALSE; /* for SEMI_STATIC data polling */ @@ -531,7 +532,7 @@ info_lkp_t kelvin_celsius_conversion[] = { * as SHUT is only supported by MGE UPS SYSTEMS units */ -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) static int match_function_subdriver(HIDDevice_t *d, void *privdata) { int i; NUT_UNUSED_VARIABLE(privdata); @@ -555,7 +556,7 @@ static HIDDeviceMatcher_t subdriver_matcher_struct = { NULL, NULL }; -#endif +#endif /* !SHUT_MODE => USB */ /* --------------------------------------------- * driver functions implementations @@ -803,7 +804,7 @@ void upsdrv_makevartable(void) addvar(VAR_FLAG, "disable_fix_report_desc", "Set to disable fix-ups for broken USB encoding, etc. which we apply by default on certain vendors/products"); -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ nut_usb_addvars(); @@ -818,10 +819,10 @@ void upsdrv_makevartable(void) addvar(VAR_VALUE, HU_VAR_WAITBEFORERECONNECT, "Seconds to wait before trying to reconnect"); -#else +#else /* SHUT_MODE */ addvar(VAR_VALUE, "notification", "Set notification type (ignored, only for backward compatibility)"); -#endif +#endif /* SHUT_MODE / USB */ } #define MAX_EVENT_NUM 32 @@ -1018,7 +1019,7 @@ void upsdrv_initups(void) dstate_getinfo("driver.version.usb"), comm_driver->name, comm_driver->version ); -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE /*! * SHUT is a serial protocol, so it needs * only the device path @@ -1026,7 +1027,7 @@ void upsdrv_initups(void) upsdebugx(1, "upsdrv_initups (SHUT)..."); subdriver_matcher = device_path; -#else +#else /* !SHUT_MODE => USB */ char *regex_array[7]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); @@ -1076,7 +1077,7 @@ void upsdrv_initups(void) /* link the matchers */ subdriver_matcher->next = regex_matcher; -#endif /* SHUT_MODE */ +#endif /* SHUT_MODE / USB */ /* Search for the first supported UPS matching the regular expression (USB) or device_path (SHUT) */ @@ -1166,7 +1167,7 @@ void upsdrv_cleanup(void) comm_driver->close_dev(udev); Free_ReportDesc(pDesc); free_report_buffer(reportbuf); -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) USBFreeExactMatcher(exact_matcher); USBFreeRegexMatcher(regex_matcher); @@ -1175,7 +1176,7 @@ void upsdrv_cleanup(void) free(curDevice.Serial); free(curDevice.Bus); free(curDevice.Device); -#endif +#endif /* !SHUT_MODE => USB */ } /********************************************************************** @@ -1232,9 +1233,9 @@ static int callback( { int i; const char *mfr = NULL, *model = NULL, *serial = NULL; -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) int ret; -#endif +#endif /* !SHUT_MODE => USB */ upsdebugx(2, "Report Descriptor size = %" PRI_NUT_USB_CTRL_CHARBUFSIZE, rdlen); #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) ) @@ -1297,7 +1298,7 @@ static int callback( } HIDDumpTree(udev, arghd, subdriver->utab); -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) /* create a new matcher for later matching */ USBFreeExactMatcher(exact_matcher); ret = USBNewExactMatcher(&exact_matcher, hd); @@ -1307,7 +1308,7 @@ static int callback( } regex_matcher->next = exact_matcher; -#endif /* SHUT_MODE */ +#endif /* !SHUT_MODE => USB */ /* apply subdriver specific formatting */ mfr = subdriver->format_mfr(hd); @@ -1373,11 +1374,11 @@ static bool_t hid_ups_walk(walkmode_t mode) double value; int retcode; -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) /* extract the VendorId for further testing */ int vendorID = curDevice.VendorID; int productID = curDevice.ProductID; -#endif +#endif /* !SHUT_MODE => USB */ /* 3 modes: HU_WALKMODE_INIT, HU_WALKMODE_QUICK_UPDATE * and HU_WALKMODE_FULL_UPDATE */ @@ -1385,13 +1386,14 @@ static bool_t hid_ups_walk(walkmode_t mode) /* Device data walk ----------------------------- */ for (item = subdriver->hid2nut; item->info_type != NULL; item++) { -#ifdef SHUT_MODE +#if (defined SHUT_MODE) && SHUT_MODE /* Check if we are asked to stop (reactivity++) in SHUT mode. * In USB mode, looping through this takes well under a second, * so any effort to improve reactivity here is wasted. */ if (exit_flag != 0) return TRUE; -#endif +#endif /* SHUT_MODE */ + /* filter data according to mode */ switch (mode) { @@ -1485,14 +1487,14 @@ static bool_t hid_ups_walk(walkmode_t mode) # pragma GCC diagnostic pop #endif -#ifndef SHUT_MODE +#if !((defined SHUT_MODE) && SHUT_MODE) /* skip report 0x54 for Tripplite SU3000LCD2UHV due to firmware bug */ if ((vendorID == 0x09ae) && (productID == 0x1330)) { if (item->hiddata && (item->hiddata->ReportID == 0x54)) { continue; } } -#endif +#endif /* !SHUT_MODE => USB */ retcode = HIDGetDataValue(udev, item->hiddata, &value, poll_interval); From 36d6914adafbe528d852372e9d4036bab2e43b66 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 13:30:52 +0200 Subject: [PATCH 0921/1232] drivers/libhid.c: HIDGetEvents(): be sure to not overflow sizeof(buf) Signed-off-by: Jim Klimov --- drivers/libhid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/libhid.c b/drivers/libhid.c index a7acdd880a..743d79bc2d 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -694,7 +694,9 @@ int HIDGetEvents(hid_dev_handle_t udev, HIDData_t **event, int eventsize) HIDData_t *pData; /* needs libusb-0.1.8 to work => use ifdef and autoconf */ - r = interrupt_size ? interrupt_size : sizeof(buf); + r = (interrupt_size > 0 && interrupt_size < sizeof(buf)) + ? interrupt_size : sizeof(buf); + #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) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_TYPE_LIMIT_COMPARE) ) # pragma GCC diagnostic push #endif From 1027c0e68c3db3e5ed57022094fb17377176eb25 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 13:40:29 +0200 Subject: [PATCH 0922/1232] drivers/usbhid-ups.c: upsdrv_initups(): only report "Initializing an USB-connected UPS with library..." when not in SHUT_MODE [#2022] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 011703d63f..2074970865 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1014,11 +1014,6 @@ void upsdrv_initups(void) int ret; char *val; - upsdebugx(2, "Initializing an USB-connected UPS with library %s " \ - "(NUT subdriver name='%s' ver='%s')", - dstate_getinfo("driver.version.usb"), - comm_driver->name, comm_driver->version ); - #if (defined SHUT_MODE) && SHUT_MODE /*! * SHUT is a serial protocol, so it needs @@ -1031,6 +1026,12 @@ void upsdrv_initups(void) char *regex_array[7]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); + + upsdebugx(2, "Initializing an USB-connected UPS with library %s " \ + "(NUT subdriver name='%s' ver='%s')", + dstate_getinfo("driver.version.usb"), + comm_driver->name, comm_driver->version ); + warn_if_bad_usb_port_filename(device_path); subdriver_matcher = &subdriver_matcher_struct; From df45a3dd20796970d77d132219cf20282be55f75 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 13:52:12 +0200 Subject: [PATCH 0923/1232] NEWS: fix for MGE SHUT broken by changes in 2.8.0 [#2022] Signed-off-by: Jim Klimov --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 5dfa768eca..7475e9ed9a 100644 --- a/NEWS +++ b/NEWS @@ -84,6 +84,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. (without specifying the single device) [#1759, #1806, #1875] * The `apcsmart` and `apcsmart-old` handled invalid data too zealously and aborted instead of skipping over it, like they did before [#2015] + * Something about compile-time macros or other warnings-related refactoring + seems to have confused the MGE SHUT (Serial HID UPS Transfer) driver + support [#2022] - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an From 2117050912563bd031e13dbc2dd4677e23de3e26 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 14:23:54 +0200 Subject: [PATCH 0924/1232] drivers/libshut.c: libshut_open(): be sure that arg_device_path is not null Signed-off-by: Jim Klimov --- drivers/libshut.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/libshut.c b/drivers/libshut.c index 2bbf725ced..f4f059f350 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -394,6 +394,10 @@ static int libshut_open( * version is at index 1 (in which case, bcdDevice == 0x0202) */ usb_ctrl_descindex hid_desc_index = 0; + if (!arg_device_path) { + fatalx(EXIT_FAILURE, "%s: arg_device_path=null", __func__); + } + upsdebugx(2, "libshut_open: using port %s", arg_device_path); /* If device is still open, close it */ From d41bde3db42d9d4b6ea49eaa364da1b325151f12 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 14:24:40 +0200 Subject: [PATCH 0925/1232] drivers/libshut.c: libshut_open(): populate curDevice->Device to be on par with USB drivers (remember a copy of arg_device_path here) Signed-off-by: Jim Klimov --- drivers/libshut.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/libshut.c b/drivers/libshut.c index f4f059f350..d1c92e847a 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -467,11 +467,13 @@ static int libshut_open( free(curDevice->Product); free(curDevice->Serial); free(curDevice->Bus); + free(curDevice->Device); memset(curDevice, '\0', sizeof(*curDevice)); curDevice->VendorID = dev_descriptor->idVendor; curDevice->ProductID = dev_descriptor->idProduct; curDevice->Bus = strdup("serial"); + curDevice->Device = strdup(arg_device_path); curDevice->bcdDevice = dev_descriptor->bcdDevice; curDevice->Vendor = strdup("Eaton"); if (dev_descriptor->iManufacturer) { @@ -512,6 +514,7 @@ static int libshut_open( upsdebugx(2, "- Product: %s", curDevice->Product); upsdebugx(2, "- Serial Number: %s", curDevice->Serial); upsdebugx(2, "- Bus: %s", curDevice->Bus); + upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); upsdebugx(2, "Device matches"); From 4fe3c78742ddb167de88c54364b6486babfea529 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 25 Aug 2023 14:58:32 +0200 Subject: [PATCH 0926/1232] drivers/libshut.c: libshut_open(): calculate desc->wDescriptorLength differently (closer to what libusbX.c do and NUT v2.7.4 did); bump driver version [#2022] Signed-off-by: Jim Klimov --- drivers/libshut.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/libshut.c b/drivers/libshut.c index d1c92e847a..79acd0ade8 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -43,7 +43,7 @@ #include "common.h" /* for xmalloc, upsdebugx prototypes */ #define SHUT_DRIVER_NAME "SHUT communication driver" -#define SHUT_DRIVER_VERSION "0.86" +#define SHUT_DRIVER_VERSION "0.87" /* communication driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -556,8 +556,7 @@ static int libshut_open( } /* USB_LE16_TO_CPU(desc->wDescriptorLength); */ - desc->wDescriptorLength = (uint16_t)(buf[7]); - desc->wDescriptorLength |= (((uint16_t)buf[8]) << 8); + desc->wDescriptorLength = (0x00FF & (uint8_t)buf[7]) | ((0x00FF & (uint8_t)buf[8]) << 8); upsdebugx(2, "HID descriptor retrieved (Reportlen = %u)", desc->wDescriptorLength); /* From f56b99ceaf594cf11a4a03986c200137a5d8c27b Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Wed, 30 Aug 2023 09:12:45 -0400 Subject: [PATCH 0927/1232] Revert "cyberpower-mib: fix instant command declarations" This reverts commit 8bcf255b624e6ba6c89a2a3eeab37658d9cb8cb4. Cyberpower `snmp_info_t` got updated to conform with pre 5d97d07 instant commands layout, but got merged after it. Reverting 8bcf255 so that command values are correctly in `su_info_t->dfl`. --- drivers/cyberpower-mib.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index d240b5c0ec..49afc959d1 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -195,22 +195,22 @@ static snmp_info_t cyberpower_mib[] = { SU_FLAG_OK | SU_TYPE_TIME, NULL }, /* instant commands. */ /* upsAdvanceControlUpsOff */ - { "load.off", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.1.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "load.off", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceControlTurnOnUPS */ - { "load.on", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "load.on", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceControlUpsOff */ - { "shutdown.stayoff", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, - /* upsAdvanceControlUpsSleep */ - { "shutdown.return", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.3.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "shutdown.stayoff", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsBaseControlConserveBattery */ + { "shutdown.return", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceControlSimulatePowerFail */ - { "test.failure.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.4.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.failure.start", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.4.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceTestIndicators */ - { "test.panel.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.5.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.panel.start", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.7.2.5.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceTestDiagnostics */ - { "test.battery.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.2.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.battery.start", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.7.2.2.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceTestRuntimeCalibration */ - { "calibrate.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "calibrate.stop", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "calibrate.start", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "calibrate.stop", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceTestLastDiagnosticsDate */ { "ups.test.date", ST_FLAG_STRING, 8, ".1.3.6.1.4.1.3808.1.1.1.7.2.4.0", "", From fbefefb2f42c2c696d502813f8c502305c54e1a6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 30 Aug 2023 19:04:23 +0200 Subject: [PATCH 0928/1232] NEWS: fix for cyberpower-mib instcmd definitions [#2029] Signed-off-by: Jim Klimov --- NEWS | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 7475e9ed9a..c65c2c12ab 100644 --- a/NEWS +++ b/NEWS @@ -66,8 +66,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. fixed for NUT v2.8.1. * A table in `cyberpower-mib` (for `snmp-ups` driver) sources was arranged in NUT v2.8.0 release in a way that precluded the driver - logic from looking at all of its entries. Regression fixed for NUT - v2.8.1 [#1432] + logic from looking at all of its entries. Also a fix for instant + command definitions had in fact broken them due to other development. + Regressions fixed for NUT v2.8.1 [#1432, #2029] * A change for file-change detection in `dummy-ups` driver for NUT v2.8.0 release misfired on some platforms. Regression fixed for NUT v2.8.1 [#1420] From d157d5fadafdd35dec5234d773ec50ccd78c28ed Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 30 Aug 2023 19:48:01 +0200 Subject: [PATCH 0929/1232] data/driver.list.in: Add APC Smart-UPS 3000 [networkupstools/nut-ddl#24] Signed-off-by: Jim Klimov --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index f51801fc0b..7af0de451a 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -85,6 +85,7 @@ "APC" "ups" "1" "Back-UPS" "940-0023A cable" "genericups upstype=9" "APC" "ups" "1" "Back-UPS Office" "940-0119A cable" "genericups upstype=12" "APC" "ups" "1" "Back-UPS RS 500" "custom non-USB cable" "genericups upstype=20" +"APC" "ups" "3" "Smart-UPS 3000" "" "snmp-ups" "APC" "ups" "3" "Smart-UPS RT XL" "AP9618 SNMP monitoring card" "snmp-ups" "APC" "ups" "3" "(various)" "AP9618 SNMP monitoring card" "snmp-ups" "APC" "ups" "3" "(various)" "AP9630 SNMP monitoring card" "snmp-ups privProtocol=AES" From aa156665482054cf63e66cca279cafc507719afa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 30 Aug 2023 20:29:46 +0200 Subject: [PATCH 0930/1232] data/driver.list.in: Add FSP Fortron UPS Champ 1000VA, 2000VA and 3000VA Towers [networkupstools/nut-ddl#22, networkupstools/nut#1691, networkupstools/nut#1741, networkupstools/nut#1872] Closes: #1691 Closes: #1741 Closes: #1872 Signed-off-by: Jim Klimov --- data/driver.list.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data/driver.list.in b/data/driver.list.in index 7af0de451a..5c81a3ca2a 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -455,6 +455,10 @@ "Forza Power Technologies" "ups" "2" "FX-1500LCD" "USB" "blazer_usb" "FSP" "ups" "2" "EP650" "USB" "blazer_usb" +"FSP" "ups" "2" "Fortron UPS Champ 1000 VA Tower" "USB" "blazer_usb" +"FSP" "ups" "2" "Fortron UPS Champ 1000 VA Tower" "USB" "nutdrv_qx" +"FSP" "ups" "2" "Fortron UPS Champ 2000 VA Tower" "USB" "blazer_usb" +"FSP" "ups" "2" "Fortron UPS Champ 3000 VA Tower" "USB" "blazer_usb" "Gamatronic" "ups" "5" "All models with alarm interface" "" "genericups upstype=22" "Gamatronic" "ups" "2" "G-SmartCompact 2000" "" "blazer_ser" @@ -1360,4 +1364,3 @@ "WTI" "pdu" "1" "RPS-10" "10 outlets" "powerman-pdu (experimental)" "WTI" "pdu" "1" "NPS" "8 outlets" "powerman-pdu (experimental)" - From 540885f7878a7b893efe298e40c975572e23f61a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 30 Aug 2023 21:26:39 +0200 Subject: [PATCH 0931/1232] data/driver.list.in: Update Riello SER/USB/SNMP HCL per vendor report [#1878] Signed-off-by: Jim Klimov --- data/driver.list.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 5c81a3ca2a..c39783e9ed 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1050,33 +1050,48 @@ "Riello" "ups" "5" "DVR 500/800/1100" "USB" "riello_usb" "Riello" "ups" "5" "DVD 1500/2200/3000" "USB" "riello_usb" "Riello" "ups" "5" "VST 800/1100/1500/2000" "USB" "riello_usb" +"Riello" "ups" "5" "VSR 800/1100" "USB" "riello_usb" "Riello" "ups" "5" "VSD 1100/1500/2200/3000" "USB" "riello_usb" "Riello" "ups" "5" "SEP 700/1000/1500/2200/3000" "USB" "riello_usb" "Riello" "ups" "5" "SDH 1000/1500/2200/3000" "USB" "riello_usb" "Riello" "ups" "5" "SDL 3300/4000/5000/6000/6500/8000/10000" "USB" "riello_usb" +"Riello" "ups" "5" "SDU 4000/5000/6000/8000/10000" "USB" "riello_usb" "Riello" "ups" "5" "SPW" "USB" "riello_usb" "Riello" "ups" "5" "SPT" "USB" "riello_usb" +"Riello" "ups" "5" "STW 5000/6000/8000/10000" "USB" "riello_usb" +"Riello" "ups" "5" "S3M" "USB" "riello_usb" +"Riello" "ups" "5" "S3T" "USB" "riello_usb" + "Riello" "ups" "5" "NDG 800/1000/1500/2000" "" "riello_ser" "Riello" "ups" "5" "DVT 500/800/1100/1500/2000" "" "riello_ser" "Riello" "ups" "5" "DVR 500/800/1100" "" "riello_ser" "Riello" "ups" "5" "DVD 1500/2200/3000" "" "riello_ser" "Riello" "ups" "5" "VST 800/1100/1500/2000" "" "riello_ser" +"Riello" "ups" "5" "VSR 800/1100" "" "riello_ser" "Riello" "ups" "5" "VSD 1100/1500/2200/3000" "" "riello_ser" "Riello" "ups" "5" "SEP 700/1000/1500/2200/3000" "" "riello_ser" "Riello" "ups" "5" "SDH 1000/1500/2200/3000" "" "riello_ser" "Riello" "ups" "5" "SDL 3300/4000/5000/6000/6500/8000/10000" "" "riello_ser" +"Riello" "ups" "5" "SDU 4000/5000/6000/8000/10000" "" "riello_ser" "Riello" "ups" "5" "SPW" "" "riello_ser" "Riello" "ups" "5" "SPT" "" "riello_ser" +"Riello" "ups" "5" "STW 5000/6000/8000/10000" "" "riello_ser" +"Riello" "ups" "5" "S3M" "" "riello_ser" +"Riello" "ups" "5" "S3T" "" "riello_ser" "Riello" "ups" "5" "MCT" "" "riello_ser" "Riello" "ups" "5" "MST" "" "riello_ser" "Riello" "ups" "5" "MCM" "" "riello_ser" "Riello" "ups" "5" "MCT" "" "riello_ser" +"Riello" "ups" "5" "MHE" "" "riello_ser" "Riello" "ups" "5" "MHT" "" "riello_ser" "Riello" "ups" "5" "MPT" "" "riello_ser" "Riello" "ups" "5" "MPM" "" "riello_ser" +"Riello" "ups" "5" "NXE" "" "riello_ser" "Riello" "ups" "3" "(various)" "Netman Plus 101 SNMP Box" "snmp-ups" "Riello" "ups" "3" "(various)" "Netman Plus 102 SNMP Card" "snmp-ups" "Riello" "ups" "3" "(various)" "Netman Plus 202 SNMP Card" "snmp-ups" +"Riello" "ups" "3" "(various)" "Netman 204 SNMP Card" "snmp-ups" +"Riello" "ups" "3" "(various)" "Netman 208 SNMP Card" "snmp-ups" "Rocketfish" "ups" "3" "RF-1000VA / RF-1025VA" "USB" "usbhid-ups" From 6c7acb2316763d81033c24486622140e1ac320b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 30 Aug 2023 21:27:34 +0200 Subject: [PATCH 0932/1232] data/driver.list.in: Update Riello SNMP HCL names (no vendor in model name usually) Signed-off-by: Jim Klimov --- data/driver.list.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/driver.list.in b/data/driver.list.in index c39783e9ed..70b7153b64 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1039,8 +1039,8 @@ "Repotec" "ups" "1" "RPT-800A" "" "genericups upstype=13" "Repotec" "ups" "1" "RPT-162A" "" "genericups upstype=13" -"Riello" "ups" "3" "Riello Sentinel SDL 6000-7" "Netman Plus 102 SNMP Card" "snmp-ups" -"Riello" "ups" "3" "Riello Sentinel Dual SDH 1000-7" "Netman Plus 102 SNMP Card" "snmp-ups" +"Riello" "ups" "3" "Sentinel SDL 6000-7" "Netman Plus 102 SNMP Card" "snmp-ups" +"Riello" "ups" "3" "Sentinel Dual SDH 1000-7" "Netman Plus 102 SNMP Card" "snmp-ups" "Riello" "ups" "4" "IDG 400/600/800/1200/1600" "USB" "riello_usb" "Riello" "ups" "4" "IPG 600/800" "USB" "riello_usb" "Riello" "ups" "5" "WPG 400/600/800" "USB" "riello_usb" From ba976a54c278572d36773843a186a640d86acd36 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 09:34:33 +0200 Subject: [PATCH 0933/1232] data/driver.list.in: Add Ippon Smart Power Pro II 1200/1600/... series [#701] Signed-off-by: Jim Klimov --- data/driver.list.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 70b7153b64..5966a93b23 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -556,6 +556,8 @@ "Ippon" "ups" "2" "Back Comfo Pro II 650/850/1050" "USB" "blazer_usb (experimental)" "Ippon" "ups" "2" "Smart Power Pro 1000/1400/2000" "" "blazer_ser" "Ippon" "ups" "2" "Smart Power Pro 1000/1400/2000" "USB" "blazer_usb (experimental)" +"Ippon" "ups" "2" "Smart Power Pro II 1200/1600/2200" "USB" "usbhid-ups" +"Ippon" "ups" "2" "Smart Power Pro II Euro 1200/1600/2200" "USB" "usbhid-ups" "Ippon" "ups" "2" "Smart Winner 750/1000/1500/2000/3000" "" "blazer_ser" "Ippon" "ups" "2" "Smart Winner 750/1000/1500/2000/3000" "USB" "blazer_usb (experimental)" "Ippon" "ups" "2" "(various)" "" "blazer_ser" From be876057dcfb13d9486bc6297c050322e79d3cfd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 10:44:10 +0200 Subject: [PATCH 0934/1232] data/driver.list.in: Add UPSonic IRT-3K 2U [#441] Signed-off-by: Jim Klimov --- data/driver.list.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 5966a93b23..3cbf64836a 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1334,6 +1334,8 @@ "UPSonic" "ups" "1" "Power Guardian" "" "genericups upstype=7" "UPSonic" "ups" "2" "PrOffice 650" "USB" "blazer_usb" "UPSonic" "ups" "2" "DS-800" "USB" "blazer_usb" +"UPSonic" "ups" "2" "IRT-3K 2U" "USB" "megatec_usb" # Worked in NUT 2.4.3 +"UPSonic" "ups" "2" "IRT-3K 2U" "USB" "nutdrv_qx" # Should work since 2.8.0; protocol broken vs. strict checks in 2.7.4; https://github.com/networkupstools/nut/issues/441#issuecomment-1288238345 "V7" "ups" "2" "UPS1RM2U1500-1E" "USB" "blazer_usb" # http://www.v7world.com/uk/ups-1500va-rack-mount-2u-eu.html https://github.com/networkupstools/nut/issues/716 From 76353c9035286fd6a484bc2f71fc25a72f1867c5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 11:24:31 +0200 Subject: [PATCH 0935/1232] Update PowerCool 1200 report nuances [#1539] Signed-off-by: Jim Klimov --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 3cbf64836a..59df0c8a5d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -963,6 +963,7 @@ "Powercool" "ups" "1" "350VA to 1600VA" "USB" "nutdrv_atcl_usb" "Powercool" "ups" "2" "650VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 product=MEC0003 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/537 "Powercool" "ups" "2" "650VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 bus=001 product=MEC0003 protocol=hunnox langid_fix=0x0409 novendor norating noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/537 +"Powercool" "ups" "2" "1200VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 product=MEC0003 protocol=hunnox subdriver=hunnox langid_fix=0x0409 novendor norating noscanlangid" # https://github.com/networkupstools/nut/pull/1539 "Powercool" "ups" "2" "1500VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 product=MEC0003 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/537 - e.g. battery percentage is not being returned "Powercool" "ups" "2" "2000VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 product=MEC0003 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/537 From b7e5f89f5a9533e18ce10b28708ea73a4a654f56 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 16:39:15 +0200 Subject: [PATCH 0936/1232] data/driver.list.in: Add UltraMax 1000SC reports [networkupstools/nut#1634] Signed-off-by: Jim Klimov --- data/driver.list.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 59df0c8a5d..82acad61b4 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1320,6 +1320,8 @@ "TS Shara" "ups" "4" "(various)" "" "nutdrv_qx" +"UltraMax" "ups" "2" "1000SC" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1634 + "UNITEK" "ups" "2" "ALPHA 500 IC" "" "blazer_ser" "UNITEK" "ups" "2" "Alpha 1000is" "" "blazer_ser" "UNITEK" "ups" "2" "Alpha 500" "" "blazer_ser" From b780b0922e0d73128b6afe76262b97bf685714d1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 16:55:35 +0200 Subject: [PATCH 0937/1232] data/driver.list.in: Add APC SmartUPS SUA1000 (SNMP) reports [#1740] Signed-off-by: Jim Klimov --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 82acad61b4..8bd73c8f5d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -85,6 +85,7 @@ "APC" "ups" "1" "Back-UPS" "940-0023A cable" "genericups upstype=9" "APC" "ups" "1" "Back-UPS Office" "940-0119A cable" "genericups upstype=12" "APC" "ups" "1" "Back-UPS RS 500" "custom non-USB cable" "genericups upstype=20" +"APC" "ups" "3" "Smart-UPS SUA 1000" "" "snmp-ups" "APC" "ups" "3" "Smart-UPS 3000" "" "snmp-ups" "APC" "ups" "3" "Smart-UPS RT XL" "AP9618 SNMP monitoring card" "snmp-ups" "APC" "ups" "3" "(various)" "AP9618 SNMP monitoring card" "snmp-ups" From 9fa7ec133cb979f007b524a011368a3e728ace9b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 31 Aug 2023 16:56:17 +0200 Subject: [PATCH 0938/1232] data/driver.list.in: Add APC SmartUPS X 750 (USB) reports [#1261] Signed-off-by: Jim Klimov --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 8bd73c8f5d..c406a067e1 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -79,6 +79,7 @@ "APC" "ups" "3" "Back-UPS XS 1000M (Back-UPS Pro 1000, Model BX1000M)" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/139 "APC" "ups" "3" "SMC2200BI-BR" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/557 "APC" "ups" "3" "Smart-UPS (USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "Smart-UPS X 750 (USB)" "USB" "usbhid-ups" "APC" "ups" "3" "CS500" "USB" "usbhid-ups (limited data available)" # https://github.com/networkupstools/nut/issues/1776#issuecomment-1377784584 "APC" "ups" "1" "Back-UPS" "940-0095A/C cables" "genericups upstype=1" "APC" "ups" "1" "Back-UPS" "940-0020B/C cables" "genericups upstype=2" From fca875985b1b5ef12c1c529b472c1db0715ff0f3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 1 Sep 2023 09:04:47 +0200 Subject: [PATCH 0939/1232] data/driver.list.in: Add APC SmartUPS 750 (SMT750I) reports [#1261] 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 c406a067e1..d35a1ff1b9 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -79,7 +79,8 @@ "APC" "ups" "3" "Back-UPS XS 1000M (Back-UPS Pro 1000, Model BX1000M)" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/139 "APC" "ups" "3" "SMC2200BI-BR" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/557 "APC" "ups" "3" "Smart-UPS (USB)" "USB" "usbhid-ups" -"APC" "ups" "3" "Smart-UPS X 750 (USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "Smart-UPS 750 (SMT750I, USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "Smart-UPS X 750 (SMX750I, USB)" "USB" "usbhid-ups" "APC" "ups" "3" "CS500" "USB" "usbhid-ups (limited data available)" # https://github.com/networkupstools/nut/issues/1776#issuecomment-1377784584 "APC" "ups" "1" "Back-UPS" "940-0095A/C cables" "genericups upstype=1" "APC" "ups" "1" "Back-UPS" "940-0020B/C cables" "genericups upstype=2" From 7a7b8854a321f6af42317925cbbca98fa712d49d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 6 Sep 2022 11:21:21 +0200 Subject: [PATCH 0940/1232] drivers/libhid.c: log if we hit the "paranoia check" with inconsistent Max vs Min [#1512] Signed-off-by: Jim Klimov --- drivers/libhid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/libhid.c b/drivers/libhid.c index 743d79bc2d..83ecceebce 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -821,6 +821,7 @@ static double logical_to_physical(HIDData_t *Data, long logical) if ((Data->PhyMax <= Data->PhyMin) || (Data->LogMax <= Data->LogMin)) { /* this should not really happen */ + upsdebugx(5, "Max was not greater than Min, returning logical value as is"); return (double)logical; } @@ -859,6 +860,7 @@ static long physical_to_logical(HIDData_t *Data, double physical) if ((Data->PhyMax <= Data->PhyMin) || (Data->LogMax <= Data->LogMin)) { /* this should not really happen */ + upsdebugx(5, "Max was not greater than Min, returning physical value as is"); return (long)physical; } From 6f4c1bf69f451def37b015824f92ec4a07eb81bd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 6 Sep 2022 14:14:44 +0200 Subject: [PATCH 0941/1232] drivers/main.c: retain "driver.parameter.override.XXX" (and ".default.XXX") for troubleshooting [#1279] Signed-off-by: Jim Klimov --- drivers/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/main.c b/drivers/main.c index 320f38bc56..91fd3beec0 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -291,13 +291,17 @@ void storeval(const char *var, char *val) * addvar() in a driver codebase. */ if (!strncasecmp(var, "override.", 9)) { + /* NOTE: No regard for VAR_SENSITIVE here */ dstate_setinfo(var+9, "%s", val); dstate_setflags(var+9, ST_FLAG_IMMUTABLE); + dparam_setinfo(var, val); return; } if (!strncasecmp(var, "default.", 8)) { + /* NOTE: No regard for VAR_SENSITIVE here */ dstate_setinfo(var+8, "%s", val); + dparam_setinfo(var, val); return; } From dd30c674f3aa8f7cecadc92f0d04cb791c764826 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 14 Sep 2022 12:03:06 +0200 Subject: [PATCH 0942/1232] configure.ac: comment that _GNU_SOURCE may be needed for strptime() detection Signed-off-by: Jim Klimov --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b438855634..5583a9b031 100644 --- a/configure.ac +++ b/configure.ac @@ -840,8 +840,10 @@ if (p == NULL || *p != '\0') return 1])], )]) AS_IF([test x"${ac_cv_func_strptime}" = xyes], [AC_DEFINE([HAVE_STRPTIME], 1, [defined if standard library has, and C standard allows, the strptime(s1,s2,tm) method])], - [AC_MSG_WARN([Optional C library routine strptime not found; a fallback implementation will be built in])] + [AC_MSG_WARN([Optional C library routine strptime not found; try adding _GNU_SOURCE; a fallback implementation will be built in])] ) +dnl Note: per Linux headers, this may need __USE_XOPEN (features.h) +dnl which is enabled by _XOPEN_SOURCE via _GNU_SOURCE on the platform. AM_CONDITIONAL([HAVE_STRPTIME], [test x"${ac_cv_func_strptime}" = "xyes"]) AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC,ts)], From 630ebed096f7832b16840ca1a8366fb8648095ec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 2 Sep 2023 13:11:44 +0200 Subject: [PATCH 0943/1232] drivers/blazer_{ser,usb}.c, drivers/nutdrv_qx.c: re-bump driver versions since master versions moved while the PR #1652 was queued Signed-off-by: Jim Klimov --- drivers/blazer_ser.c | 2 +- drivers/blazer_usb.c | 2 +- drivers/nutdrv_qx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/blazer_ser.c b/drivers/blazer_ser.c index 85bffa557c..f0cd90e4e8 100644 --- a/drivers/blazer_ser.c +++ b/drivers/blazer_ser.c @@ -31,7 +31,7 @@ #include "blazer.h" #define DRIVER_NAME "Megatec/Q1 protocol serial driver" -#define DRIVER_VERSION "1.59" +#define DRIVER_VERSION "1.60" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 549019158e..6cb3337ad7 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -37,7 +37,7 @@ #endif #define DRIVER_NAME "Megatec/Q1 protocol USB driver" -#define DRIVER_VERSION "0.15" +#define DRIVER_VERSION "0.16" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 616654d6c5..15c0a3073a 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -57,7 +57,7 @@ #define DRIVER_NAME "Generic Q* Serial driver" #endif /* QX_USB */ -#define DRIVER_VERSION "0.34" +#define DRIVER_VERSION "0.35" #ifdef QX_SERIAL #include "serial.h" From 6c0032e52d60a554052bda4e158f9f5f791e9561 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 4 Sep 2023 23:48:42 +0200 Subject: [PATCH 0944/1232] drivers/nutdrv_qx.c: dial back down the batt.volt.high guesstimation to 130/120 of the nominal (back from experimental 150/120) [#1652] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 15c0a3073a..83ab443a87 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -345,9 +345,14 @@ static void qx_initbattery(void) /* Per https://www.csb-battery.com.tw/english/01_product/02_detail.php?fid=17&pid=113 * a nominally 12V battery can have "float charging voltage" * at 13.5-13.8V and an "equalization charging voltage" (e.g. - * to desulphurize) at 14-15V: + * to desulphurize) at 14-15V. Note that per nut-names.txt, + * the "battery.voltage.high" is the practical 100% charge + * value (so equal or a bit less than actual battery.voltage + * reported by the device, when the situation is healthy); + * it is not the voltage that the battery CAN reach on the + * brink of boiling out: */ - batt.volt.high = 150 * batt.volt.nom / 120; + batt.volt.high = 130 * batt.volt.nom / 120; /* Publish these data too */ dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low); From d7678dd71b67d5c5580abb8007134f81be9449e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 5 Sep 2023 10:30:12 +0200 Subject: [PATCH 0945/1232] drivers/blazer.c: fix typo in comment Signed-off-by: Jim Klimov --- drivers/blazer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/blazer.c b/drivers/blazer.c index 0960fa96bb..41f0a20f5b 100644 --- a/drivers/blazer.c +++ b/drivers/blazer.c @@ -132,7 +132,7 @@ static double blazer_load(const char *ptr, char **endptr) /* * The battery voltage will quickly return to at least the nominal value after - * discharging them. For overlapping battery.voltage.low/high ranges therefor + * discharging them. For overlapping battery.voltage.low/high ranges therefore * choose the one with the highest multiplier. */ static double blazer_packs(const char *ptr, char **endptr) From 6569b978c24cf1a6da881f4ad7362028af623972 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 5 Sep 2023 10:42:14 +0200 Subject: [PATCH 0946/1232] drivers/snmp-ups.c: add a TODO for multi-MIB approach [#2036] Signed-off-by: Jim Klimov --- drivers/snmp-ups.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 558c72e61f..aef198cba8 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -616,6 +616,13 @@ void upsdrv_initups(void) /* FIXME: first test if the device is reachable to avoid timeouts! */ + /* FIXME: with the argument called "mibs" (plural) it could make + * sense to actually support a list of MIBs to try to get info + * from, in order of preference, e.g. both a vendor MIB and the + * IETF MIB for missing data points. Or even several vendor MIBs + * for devices from companies with a long heritage. + */ + /* Load the SNMP to NUT translation data */ load_mib2nut(mibs); From 2a20d3990c0766081879b2eb39a3ac41aa16b98e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 5 Sep 2023 10:47:37 +0200 Subject: [PATCH 0947/1232] drivers/snmp-ups.c, NEWS: clearer messages for skipped mib2nut mappings New message example: 0.001836 [D2] load_mib2nut: skip the "tripplite" entry from the mapping table which is not "ietf" (and which in turn is not "auto") Signed-off-by: Jim Klimov --- NEWS | 1 + drivers/snmp-ups.c | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index c65c2c12ab..101b95fb02 100644 --- a/NEWS +++ b/NEWS @@ -153,6 +153,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - snmp-ups updates: * Fixed detection for device agents which wrongly return the sysOID value as a string instead of an OID [#1710] + * Clearer messages about skipping MIBs during driver initialization [#2037] * IETF MIB mapping updated for data points where negative readings are invalid [#1558] * Added SNMP subdriver "apc-epdu-mib" for APC easy PDU support [#1674] diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index aef198cba8..fa108c9b37 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -2042,9 +2042,10 @@ bool_t load_mib2nut(const char *mib) __func__, i, mib2nut[i]->mib_name); if (!mibIsAuto && strcmp(mib, mib2nut[i]->mib_name)) { /* "mib" is neither "auto" nor the name in mapping table */ - upsdebugx(2, "%s: skip the \"%s\" entry which " - "is neither \"auto\" nor a valid name in the mapping table", - __func__, mib); + upsdebugx(2, "%s: skip the \"%s\" entry from " + "the mapping table which is not \"%s\" " + "(and which in turn is not \"auto\")", + __func__, mib2nut[i]->mib_name, mib); continue; } upsdebugx(2, "%s: trying classic sysOID matching method with '%s' mib", @@ -2114,7 +2115,9 @@ bool_t load_mib2nut(const char *mib) /* String not seen during mib2nut[] walk - * and if we had no hits, we walked it all */ - fatalx(EXIT_FAILURE, "Unknown 'mibs' value: %s", mib); + fatalx(EXIT_FAILURE, "Unknown 'mibs' value " + "which is neither \"auto\" nor a valid " + "name in the mapping table: %s", mib); } } else { fatalx(EXIT_FAILURE, "No supported device detected at [%s] (host %s)", From e0dfca2d6fd654699cf9974a7a64de3b5d7d7a45 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 5 Sep 2023 10:49:01 +0200 Subject: [PATCH 0948/1232] NEWS: formatting fix Signed-off-by: Jim Klimov --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 101b95fb02..fe84ac69fc 100644 --- a/NEWS +++ b/NEWS @@ -165,7 +165,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. SNMP v3 to get both read and write rights [#1713] * Fixed processing loop for large SNMPv2/SNMPv3 responses where one item in the middle has a type error [#1682] - * Better manage the slight nuances (especially in ups.status) between + * Better manage the slight nuances (especially in `ups.status`) between Eaton UPSs, and rename mibs from `pw` to `eaton_pw_nm2`, and from `pxgx_ups` to `eaton_pxg_ups` [#1715] * Fixed the long standing "Warning: excessive poll failures" issue, that From ebd58f8f72db339b1eb4024b3ea64a8bbc67752d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 5 Sep 2023 12:12:40 +0200 Subject: [PATCH 0949/1232] drivers/main.c: comment why we do not solve VAR_SENSITIVE for override/default right now [#1891] Signed-off-by: Jim Klimov --- drivers/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/main.c b/drivers/main.c index 91fd3beec0..c48e291ef7 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -288,7 +288,12 @@ void storeval(const char *var, char *val) /* NOTE: (FIXME?) The override and default mechanisms here * effectively bypass both VAR_SENSITIVE protections and * the constraint of having previously defined the name by - * addvar() in a driver codebase. + * addvar() in a driver codebase, or of having a dot in it. + * See https://github.com/networkupstools/nut/issues/1891 + * if this would need solving eventually. At the moment the + * sensitivity impacts certain auth values for netxml-ups + * and snmp-ups reading from vartab directly, and overrides + * are ignored - so no practical problem to solve right now. */ if (!strncasecmp(var, "override.", 9)) { /* NOTE: No regard for VAR_SENSITIVE here */ From 3472f0b6f035f5e3080bdd09902631d115dd7bb4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 6 Sep 2023 16:00:07 +0200 Subject: [PATCH 0950/1232] drivers/cyberpower-mib.c: restore upsAdvanceControlUpsSleep as "shutdown.return" [follow-up from #2029] Signed-off-by: Jim Klimov --- drivers/cyberpower-mib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index 49afc959d1..77945f95a9 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -200,8 +200,15 @@ static snmp_info_t cyberpower_mib[] = { { "load.on", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceControlUpsOff */ { "shutdown.stayoff", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - /* upsBaseControlConserveBattery */ +#if 0 + /* upsBaseControlConserveBattery - note that this command + * is not suitable here because it puts ups to sleep only + * in battery mode. If power is restored during the shutdown + * process, the command is not executed by ups hardware. */ { "shutdown.return", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, +#endif + /* upsAdvanceControlUpsSleep */ + { "shutdown.return", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.3.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceControlSimulatePowerFail */ { "test.failure.start", 0, 1, ".1.3.6.1.4.1.3808.1.1.1.6.2.4.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* upsAdvanceTestIndicators */ From 9e6f1d931ab9eb6c43f975b4ff96064a326d4f70 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 7 Sep 2023 13:09:20 +0200 Subject: [PATCH 0951/1232] Update cyberpower-mib.c Bump version after #2041 --- drivers/cyberpower-mib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index 77945f95a9..8c73ac92f0 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -24,7 +24,7 @@ #include "cyberpower-mib.h" -#define CYBERPOWER_MIB_VERSION "0.54" +#define CYBERPOWER_MIB_VERSION "0.55" #define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" /* CPS-MIB::ups */ From d69b2d010611ddf5ce4abdc25508a72b17bdb6a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 16:41:33 +0200 Subject: [PATCH 0952/1232] docs/hid-subdrivers.txt: add a "screenshot" of rexx usage Signed-off-by: Jim Klimov --- docs/hid-subdrivers.txt | 61 +++++++++++++++++++++++++++++++++++++++-- docs/nut.dict | 12 +++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/docs/hid-subdrivers.txt b/docs/hid-subdrivers.txt index 253bb2cab3..1657735423 100644 --- a/docs/hid-subdrivers.txt +++ b/docs/hid-subdrivers.txt @@ -312,7 +312,8 @@ multiple-byte ranges in a protocol buffer. For a deep dive into the byte stream, you will need additional tools: * get/build/install link:https://regina-rexx.sourceforge.io[regina-rexx] -* get/install link:https://github.com/abend0c1/hidrdd[HIDRDD] +* get/install link:https://github.com/abend0c1/hidrdd[HIDRDD] (uses REXX + as the interpreter) Typical troubleshooting of suspected firmware/protocol issues goes like this: @@ -321,7 +322,8 @@ Typical troubleshooting of suspected firmware/protocol issues goes like this: * Look for reports from the driver of any problems it has already detected and possibly amended (LogMin/LogMax, report descriptor fix-ups) * Extract the HEX dump of the report descriptor from USB driver output from - the first step above, and run it through HIDRDD + the first step above, and run it through HIDRDD (and/or REXX directly, + per example below). * Look at the HIDRDD output, with reference to any documents related to your device and the USB/HID power devices class available in NUT documentation, e.g. at https://www.networkupstools.org/ups-protocols.html @@ -337,6 +339,61 @@ Typical troubleshooting of suspected firmware/protocol issues goes like this: for where the result deviates from expectations... * Think, code, test, rinse, repeat, post a PR :) +.Example direct use of REXX +=========================== +Example adapted from https://github.com/networkupstools/nut/issues/2039 + +Run a NUT `usb-hid` driver with at least debug verbosity level 3 (`-DDD`) +to get a report descriptor dump starting with a line like this: +---- + 3.670755 [D3] Report Descriptor: (909 bytes) => 05 84 09 04 a1 01 ... +---- + +...and copy-paste those reported lines as input into `rexx` tool, which +would generate a C source file including human-worded description and +a relevant data structure: + +---- +:; rexx rd.rex -d --hex 05 84 09 04 a1 01 85 01 09 18 ... 55 b1 02 c0 c0 c0 + +//-------------------------------------------------------------------------------- +// Decoded Application Collection +//-------------------------------------------------------------------------------- + +/* +05 84 (GLOBAL) USAGE_PAGE 0x0084 Power Device Page +09 04 (LOCAL) USAGE 0x00840004 UPS (Application Collection) +A1 01 (MAIN) COLLECTION 0x01 Application (Usage=0x00840004: Page=Power Device Page, Usage=UPS, Type=Application Collection) +85 01 (GLOBAL) REPORT_ID 0x01 (1) +09 18 (LOCAL) USAGE 0x00840018 Outlet System (Physical Collection) +... +*/ + +// All structure fields should be byte-aligned... +#pragma pack(push,1) + +//-------------------------------------------------------------------------------- +// Power Device Page featureReport 01 (Device <-> Host) +//-------------------------------------------------------------------------------- + +typedef struct +{ + uint8_t reportId; // Report ID = 0x01 (1) + // Collection: CA:UPS CP:OutletSystem CP:Outlet + int8_t POW_UPSOutletSystemOutletSwitchable; // Usage 0x0084006C: Switchable, Value = to + int8_t POW_UPSOutletSystemOutletDelayBeforeStartup; // Usage 0x00840056: Delay Before Startup, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletDelayBeforeShutdown; // Usage 0x00840057: Delay Before Shutdown, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletDelayBeforeReboot; // Usage 0x00840055: Delay Before Reboot, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletSwitchable_1; // Usage 0x0084006C: Switchable, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletDelayBeforeStartup_1; // Usage 0x00840056: Delay Before Startup, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletDelayBeforeShutdown_1; // Usage 0x00840057: Delay Before Shutdown, Value = -1 to 60 + int8_t POW_UPSOutletSystemOutletDelayBeforeReboot_1; // Usage 0x00840055: Delay Before Reboot, Value = -1 to 60 +} featureReport01_t; + +#pragma pack(pop) +---- +=========================== + Shutting down the UPS ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/nut.dict b/docs/nut.dict index 028feaaea8..508eeb7cc6 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3198 utf-8 +personal_ws-1.1 en 3208 utf-8 AAS ABI ACFAIL @@ -852,6 +852,7 @@ Opti OptiUPS Orvaldi Orzechowski +OutletSystem OutputOverload OvrLds PBT @@ -1020,6 +1021,7 @@ REPLBATT REQSSL RESPIN RETPCT +REXX RK RMCARD RMXL @@ -1308,6 +1310,10 @@ UPSDESC UPSHOST UPSIMAGEPATH UPSLC +UPSOutletSystemOutletDelayBeforeReboot +UPSOutletSystemOutletDelayBeforeShutdown +UPSOutletSystemOutletDelayBeforeStartup +UPSOutletSystemOutletSwitchable UPSSTATSPATH UPSTEMP UPScode @@ -1927,6 +1933,7 @@ fcntl fd fds fe +featureReport fenton fentonups fffdddxxx @@ -2679,6 +2686,7 @@ regtype releasekeyring relicensing repo +reportId reposurgeon repotec req @@ -2690,6 +2698,8 @@ ret retrydelay revdate revnumber +rex +rexx rf rfc rh From 9fb17b996e90a15d446e939522aee11163f552a4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 16:42:01 +0200 Subject: [PATCH 0953/1232] docs/new-drivers.txt: cosmetix fix (indent) Signed-off-by: Jim Klimov --- docs/new-drivers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index 1174d71789..8503a38287 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -95,7 +95,7 @@ This structure tracks several description information about the driver: - DRV_COMPLETE: this is the gold level! It implies that 100 % of the protocol is implemented, and a full QA pass. * *subdrv_info*: array of upsdrv_info_t for sub driver(s) information. For - example, this is used by usbhid-ups. + example, this is used by usbhid-ups. This information is currently used for the startup banner printing and tests. From 98ee05919bf96078dc508f0f18d88df19d2fb9fd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 17:18:19 +0200 Subject: [PATCH 0954/1232] docs/developers.txt: fix section-level warning, and add AppVeyor CI and CircleCI sections Signed-off-by: Jim Klimov --- docs/developers.txt | 24 ++++++++++++++++++++++++ docs/nut.dict | 5 ++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/developers.txt b/docs/developers.txt index 5ff7db481e..0c3f1244d3 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -171,6 +171,9 @@ To ease and automate the build scenarios which were deemed important for quality assurance and non-regression checks of NUT, several solutions were introduced over time. +Build automation tools and scripts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ci_build.sh ^^^^^^^^^^^ @@ -354,6 +357,27 @@ Some further details about the NUT CI farm workers are available in link:config-prereqs.txt[config-prereqs.txt] and link:ci-farm-lxc-setup.txt[ci-farm-lxc-setup.txt] documents. +AppVeyor CI +^^^^^^^^^^^ + +Primarily used for building NUT for Windows on Windows instances provided +in the cloud -- and so ensure non-regression as well as downloadable archives +with binary installation prototype area, intended for enthusiastic testing +(proper packaging to follow). NUT for Windows build-ability was re-introduced +soon after NUT 2.8.0 release. + +This relies on a few prerequisite packages and a common NUT configuration, +as coded in the `appveyor.yml` file in the NUT codebase. + +CircleCI +^^^^^^^^ + +Primarily used for building NUT for MacOS on instances provided in the cloud, +and so ensure non-regression across several Xcode releases. + +This relies on a few prerequisite packages and a common NUT configuration, +as coded in the `.circleci/config.yml` file in the NUT codebase. + Travis CI ^^^^^^^^^ diff --git a/docs/nut.dict b/docs/nut.dict index 508eeb7cc6..0276096d3a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3208 utf-8 +personal_ws-1.1 en 3211 utf-8 AAS ABI ACFAIL @@ -1503,6 +1503,7 @@ apcsmart apctest apcupsd aphel +appveyor ar archlinux arduino @@ -3194,6 +3195,8 @@ xu xxxAP xxxx xxxxAP +yaml +yml youruid yyy zaac From ac790eb63fbf2fb6d7cab165df2f7edfa8a60fa2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 17:46:33 +0200 Subject: [PATCH 0955/1232] docs/maintainer-guide.txt: update release procedure Signed-off-by: Jim Klimov --- docs/maintainer-guide.txt | 67 ++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index ea5d5e6794..e31eab7267 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -43,7 +43,7 @@ These are the general rules that apply to mailing list moderation: to store the file(s). - other (ie report or request requiring more than 1 mail): REJECT with a -message explaining the reason. The following can serve as a base: + message explaining the reason. The following can serve as a base: Dear XXX, Your message to the nut-upsXXX mailing was rejected because you must @@ -66,29 +66,72 @@ Release process New process: - we will only work on the trunk for the day to day bugfixing and -standard modifications (what was mostly happening in Testing -currently), + standard modifications (what was mostly happening in Testing + currently), - the trunk will be used to generate the testing releases (only using -the tags, after a small freeze period), + the tags, after a small freeze period), - bigger changes, invasive modifications and cutting edge developments -will have to be addressed in separate branches, until stabilization. -When things are ok and validated to enter the trunk, merging these -branches into the trunk can happen. + will have to be addressed in separate branches, until stabilization. + When things are ok and validated to enter the trunk, merging these + branches into the trunk can happen. + I insist on the *validation* to enter the trunk, since some changes might have to wait for major releases, to match our current release process. SANDBOX (to be completed and pushed) -* update version to (ex: 2.7.3) in nut/configure.ac +* clean up "in-development" bits from files, e.g.: +** TODO etc. referring planned future in the `NEWS` and `UPDATING` files +** comment away the top-most (auto-resolved) NUT version and build date + in `docs/docinfo.xml.in` -- DO NOT add (or at least commit) an entry + for the actual fixed release version and date just yet +** commit this change (to add a revert-commit after the release tag) + +* bump the release identification: +** add an entry in `docs/docinfo.xml` for the actual fixed release version + and date +** update version to (ex: 2.7.3) in nut/configure.ac +** revise the `NEWS` and `UPDATING` files +** generate/revise Changelog if needed + * create a GPG-signed tag v (ex: v2.7.3) ** try to avoid adding signed tags later (ex. v2.8.0-signed) to avoid the mess in GitHub release URLs (or do amend that post-factum), for more details see e.g. https://github.com/networkupstools/nut/issues/1971 -* `make dist` -* maybe update nut/configure.ac version to .1 (ex: 2.7.3.1) + +* `make dist` to store the source tarball, checksum and signature iles + +* post-release update of the "in-development" codebase: +** maybe update nut/configure.ac version to .1 (ex: 2.7.3.1) +** `git revert` the commit which cleaned up "in-development" bits above +** Possibly resolve relevant merge conflicts for the changed context + * push commits and tag -* update nut/ and ddl/ submodules in nut-website/ (this should update the website's version as well) -* add download hashes for tarball + +* Update `nut-website`: +** rendering should auto-update by NUT CI farm based on source changes, + but in case of urgency -- can be expedited with a prepared workstation + (see README of that project) or from the NUT CI farm agent directly +** add an entry to `news.txt` +** update `nut` and `ddl` submodules in nut-website/ to refer to latest info + as of current release (this should update the website's version as well). + NOTE: for `nut` submodule be sure to refer to the tagged commit, not to + the subsequent "in-development" codebase. +** in `source` submodule add a copy of tarball, checksum and hash files for + download +** `git tag` the website release +** generate and publish a "historic" sub-site snapshot (currently manually) +** update `nut` submodule to current commit ("in-development" codebase), and + the `historic/index.txt` to refer to the snapshot for reference (users of + specific-version packages) +** generate and publish the usual website revision (by CI or manually) + +* check that the website renders properly + +* draft and publish a GitHub release based on the signed tag +** attach the same copy of tarball, checksum and hash files as for nut-website + +* announce on mailing list, IRC, etc. ////////////////////////////////////////////////////////////////////////////// From da74d386d76740536a13454658d35c56b65a24af Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 18:33:47 +0200 Subject: [PATCH 0956/1232] docs/developer-guide.txt: update author list Signed-off-by: Jim Klimov --- docs/developer-guide.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 5cd8f2c2f8..6b0090edc0 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -2,8 +2,8 @@ Network UPS Tools Developer Guide _________________________________ -:Author: Russell_Kroll,_Arnaud_Quette,_Charles_Lepple_and_Peter_Selinger -:Author Initials: RK, AQ, CL & PS +:Author: Russell_Kroll,_Arnaud_Quette,_Charles_Lepple,_Peter_Selinger,_Jim_Klimov_and_NUT_project_community_contributors +:Author Initials: RK, AQ, CL, PS & JK Introduction ============ From 25101f01750a3574921ce587132d2b250e6a4c7b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 18:34:27 +0200 Subject: [PATCH 0957/1232] docs/docinfo.xml.in: update "current version (snapshot)" comment Signed-off-by: Jim Klimov --- docs/docinfo.xml.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index ed3faaf311..c2a336f51f 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -1,12 +1,12 @@ - + @PACKAGE_VERSION@ @now@ - Current release of Network UPS Tools (NUT). + Current release snapshot of Network UPS Tools (NUT). From a29071189079db6a2bbb8fc80a4d6d5ee1475a8a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 18:41:11 +0200 Subject: [PATCH 0958/1232] configure.ac: update comments Signed-off-by: Jim Klimov --- configure.ac | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 5583a9b031..3591e0432f 100644 --- a/configure.ac +++ b/configure.ac @@ -6,11 +6,14 @@ dnl NUT version number is defined here, with a Git suffixed macro like dnl NUT_VERSION_MACRO "2.7.4-2838-gdfc3ac08" dnl in include/nut_version.h (generated by make) AC_INIT([nut],[2.8.0.1],[https://github.com/networkupstools/nut/issues]) +dnl See docs/maintainer-guide.txt about releases - updating the version +dnl above is a small part of the consistent ritual! dnl Note: this refers to GITREV at the time of configure script running dnl primarily for better messaging in the script itself. dnl If the NUT codebase in this workspace is being developed and rebuilt -dnl without reconfiguration, detailed version in the binaries will differ. +dnl without reconfiguration, detailed version in the binaries will differ +dnl (that one comes from the NUT_VERSION_MACRO from nut_version.h file). (command -v git >/dev/null 2>/dev/null) \ && NUT_SOURCE_GITREV="`(git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" \ || NUT_SOURCE_GITREV="" From b3d35b4f1948b4c0c40e9fd932c03d935f72492f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 18:42:03 +0200 Subject: [PATCH 0959/1232] configure.ac, docs/docinfo.xml.in: use current NUT_SOURCE_GITREV for doc revision history if available Signed-off-by: Jim Klimov --- configure.ac | 4 +++- docs/docinfo.xml.in | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 3591e0432f..b2619d2c90 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,8 @@ dnl See docs/maintainer-guide.txt about releases - updating the version dnl above is a small part of the consistent ritual! dnl Note: this refers to GITREV at the time of configure script running -dnl primarily for better messaging in the script itself. +dnl primarily for better messaging in the script itself (also to render +dnl the PDF documentation revision history via docs/docinfo.xml.in). dnl If the NUT codebase in this workspace is being developed and rebuilt dnl without reconfiguration, detailed version in the binaries will differ dnl (that one comes from the NUT_VERSION_MACRO from nut_version.h file). @@ -3890,6 +3891,7 @@ AC_SUBST(OS_NAME) AC_SUBST(TREE_VERSION) AC_SUBST(NUT_NETVERSION) AC_SUBST(FORCE_NUT_VERSION) +AC_SUBST(NUT_SOURCE_GITREV) AC_SUBST(LIBSSL_CFLAGS) AC_SUBST(LIBSSL_LIBS) AC_SUBST(LIBSSL_REQUIRES) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index c2a336f51f..9adb101e36 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -2,7 +2,7 @@ - @PACKAGE_VERSION@ + @PACKAGE_VERSION@ @NUT_SOURCE_GITREV@ @now@ From 98d0d265269228853a3dc3008b43037ed462253b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 19:10:06 +0200 Subject: [PATCH 0960/1232] tools/gitlog2changelog.py.in: bump (C) Signed-off-by: Jim Klimov --- tools/gitlog2changelog.py.in | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gitlog2changelog.py.in b/tools/gitlog2changelog.py.in index 12b80ad3e0..f4c1fd3c1f 100755 --- a/tools/gitlog2changelog.py.in +++ b/tools/gitlog2changelog.py.in @@ -1,6 +1,7 @@ #!@PYTHON@ # Copyright 2008 Marcus D. Hanwell # Minor changes for NUT by Charles Lepple +# Subsequent maintenance for NUT by Jim Klimov (since 2021) # Distributed under the terms of the GNU General Public License v2 or later import re From 75261829ee79c8378d3c9a406361a26b3151cded Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 22:26:08 +0200 Subject: [PATCH 0961/1232] Introduce docs/docinfo.xml.sh to help maintain docinfo.xml.in (currently limited to ensuring presence of existing tags) [#2046] Signed-off-by: Jim Klimov --- docs/.gitignore | 1 + docs/Makefile.am | 2 +- docs/docinfo.xml.in | 1 + docs/docinfo.xml.sh | 64 +++++++++++++++++++++++++++++++++++++++ docs/maintainer-guide.txt | 3 ++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100755 docs/docinfo.xml.sh diff --git a/docs/.gitignore b/docs/.gitignore index 555adc4b4a..b1abd8207f 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -23,3 +23,4 @@ nut.dict.sorted /*.bak /*.bak-* /tmp/ +docinfo.xml.in.tmp diff --git a/docs/Makefile.am b/docs/Makefile.am index e05aae8bf2..f07eeb9485 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -139,7 +139,7 @@ check-man all-man man-man all-html html-man: man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all -CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css +CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp # Dirs to clean clean-local: diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index 9adb101e36..2207f3f010 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -11,6 +11,7 @@ + 2.6.0 2011-01-14 diff --git a/docs/docinfo.xml.sh b/docs/docinfo.xml.sh new file mode 100755 index 0000000000..bb18d86bd9 --- /dev/null +++ b/docs/docinfo.xml.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +# Helper script to generate DOCINFO document revision list for NUT PDF docs. +# Primarily used by maintainers as part of a NUT release preparation - +# see docs/maintainer-guide.txt for more details. +# Note that relying on git tags alone is a chicken-and-egg problem here +# (the updated file should be part of a new release), so it rather helps +# catch up with missed entries. +# Copyright (C) 2023 by Jim Klimov +# Licensed under GPLv2+ terms + +SCRIPTDIR="`dirname "$0"`" \ +&& SCRIPTDIR="`cd "${SCRIPTDIR}" && pwd`" \ +&& [ -n "${SCRIPTDIR}" ] && [ -d "${SCRIPTDIR}" ] \ +|| exit + +[ -n "${DOCINFO_XML-}" ] || DOCINFO_XML="${SCRIPTDIR}/docinfo.xml.in" + +generate_tags() { + # NUT v2.6.0 is the oldest release with asciidoc rendered into PDF + for RELTAG in `git tag -l 'v*' --contains v2.6.0 | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sed -e 's,-.*$,,' | sort -nr | uniq` ; do + NUT_RELEASE="`echo "$RELTAG" | sed -e 's,^v,,'`" + grep "${NUT_RELEASE}" "${DOCINFO_XML}" >/dev/null 2>&1 && continue + + NUT_RELEASER="`git log -1 --pretty=format:'%cn' "${RELTAG}" | tr -d 'a-z '`" + # Beware to not use "|" in formatting below! Used for sed magic later. + git log -1 --pretty=tformat:' %n @NUT_RELEASE@%n %cs%n @NUT_RELEASER@%n %n %n' \ + "${RELTAG}" \ + | sed \ + -e 's,@NUT_RELEASE@,'"${NUT_RELEASE}"',' \ + -e 's,@NUT_RELEASER@,'"${NUT_RELEASER}"',' + done +} + +NEWTAGS="`generate_tags`" +[ -n "$NEWTAGS" ] || { echo "SKIP: No new releases found (without a record in DOCINFO)" >&2; exit 0; } + +#echo "TODO: Add the following DOCINFO tags:" >&2 +#echo "NEWTAGS: $NEWTAGS" >&2 + +# Have to hide and un-hide EOLs (via "|") and escape +# the leading space to enforce it in "sed a" command +# (it eats whitespace otherwise). +echo "INJECTING to DOCINFO_XML:" >&2 +NEWTAGS_SED="`echo "$NEWTAGS" | tr '\n' '|' | sed -e 's,\([/<>]\),\\1,g' -e 's,^ ,\\\\ ,'`" || exit +echo "NEWTAGS_SED: $NEWTAGS_SED" >&2 + +sed -e '//a'"$NEWTAGS_SED" \ + < "${DOCINFO_XML}" \ + | tr '|' '\n' \ + > "${DOCINFO_XML}.tmp" + +diff -bu "${DOCINFO_XML}" "${DOCINFO_XML}.tmp" + +echo "Was the change acceptable? Press Y to modify the original '${DOCINFO_XML}' file [Y/N]" >&2 +read LINE +case "$LINE" in + y|Y|yes|YES) + mv -f "${DOCINFO_XML}.tmp" "${DOCINFO_XML}" + echo "You may want to: git add -p `basename "${DOCINFO_XML}"`" >&2 + echo "...and: make `basename "${DOCINFO_XML}" .in`" >&2 + ;; + *) echo "NOT APPLYING the change! See '${DOCINFO_XML}.tmp' for investigation!" >&2 +esac diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index e31eab7267..331da3ae75 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -86,6 +86,9 @@ SANDBOX (to be completed and pushed) ** comment away the top-most (auto-resolved) NUT version and build date in `docs/docinfo.xml.in` -- DO NOT add (or at least commit) an entry for the actual fixed release version and date just yet +** NOTE: The `docs/docinfo.xml.sh` script can help update the list for + existing git tags, if some were skipped before. This can be used to + cheat a bit about adding the new entry (with a draft tag). ** commit this change (to add a revert-commit after the release tag) * bump the release identification: From 79c435cf2ed49713a2b13492dcdae55d65dc1af1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 10 Sep 2023 22:33:03 +0200 Subject: [PATCH 0962/1232] docs/docinfo.xml.in: update to list releases 2.6.1-2.8.0 missed before [#2046] First use of docinfo.xml.sh - looks decent Signed-off-by: Jim Klimov --- docs/docinfo.xml.in | 72 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index 2207f3f010..29053bd8b3 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -12,10 +12,80 @@ + + 2.8.0 + 2022-04-26 + JK + + + + + 2.7.4 + 2016-03-09 + AQ + + + + + 2.7.3 + 2015-04-22 + AQ + + + + + 2.7.2 + 2014-04-17 + AQ + + + + + 2.7.1 + 2013-11-19 + CL + + + + + 2.6.5 + 2012-08-08 + AQ + + + + + 2.6.4 + 2012-05-31 + AQ + + + + + 2.6.3 + 2012-01-04 + AQ + + + + + 2.6.2 + 2011-09-15 + AQ + + + + + 2.6.1 + 2011-06-01 + AQ + + + 2.6.0 2011-01-14 - + AQ First release of AsciiDoc documentation for Network UPS Tools (NUT). From e04f7d2fa56ecf7bc8c3d9366e89ef65f95b2b99 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 01:24:50 +0200 Subject: [PATCH 0963/1232] Update nut.dict Signed-off-by: Jim Klimov --- docs/nut.dict | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 0276096d3a..1b2b243c79 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3211 utf-8 +personal_ws-1.1 en 3213 utf-8 AAS ABI ACFAIL @@ -172,6 +172,7 @@ CERTREQUEST CERTVERIF CEST CHRG +CL CLANGVER CLI CLOCAL @@ -533,6 +534,7 @@ Ioannou JAWAN JBUS JBus +JK JKL JRE JSON From fa8721d98ee3031daed234d50643074e65a9c3a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 10:29:14 +0200 Subject: [PATCH 0964/1232] docs/docinfo.xml.sh: reference the NEWS file (GitHub URL for interactive PDFs) [#2046] Signed-off-by: Jim Klimov --- docs/docinfo.xml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docinfo.xml.sh b/docs/docinfo.xml.sh index bb18d86bd9..4b732c17a3 100755 --- a/docs/docinfo.xml.sh +++ b/docs/docinfo.xml.sh @@ -24,7 +24,7 @@ generate_tags() { NUT_RELEASER="`git log -1 --pretty=format:'%cn' "${RELTAG}" | tr -d 'a-z '`" # Beware to not use "|" in formatting below! Used for sed magic later. - git log -1 --pretty=tformat:' %n @NUT_RELEASE@%n %cs%n @NUT_RELEASER@%n %n %n' \ + git log -1 --pretty=tformat:' %n @NUT_RELEASE@%n %cs%n @NUT_RELEASER@%n %n See also: link:https://raw.githubusercontent.com/networkupstools/nut/'"${RELTAG}"'/NEWS[NEWS file for the NUT '"${RELTAG}"' release]%n %n %n' \ "${RELTAG}" \ | sed \ -e 's,@NUT_RELEASE@,'"${NUT_RELEASE}"',' \ From 46008c73f8520a0b45cf91988cb357de79248805 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 10:30:19 +0200 Subject: [PATCH 0965/1232] docs/docinfo.xml.in: populate "refremark" fields [#2046] Signed-off-by: Jim Klimov --- docs/docinfo.xml.in | 47 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index 29053bd8b3..f0f9453da7 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -16,70 +16,94 @@ 2.8.0 2022-04-26 JK - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.8.0/NEWS[NEWS file for the NUT v2.8.0 release] + 2.7.4 2016-03-09 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.4/NEWS[NEWS file for the NUT v2.7.4 release] + 2.7.3 2015-04-22 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.3/NEWS[NEWS file for the NUT v2.7.3 release] + 2.7.2 2014-04-17 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.2/NEWS[NEWS file for the NUT v2.7.2 release] + 2.7.1 2013-11-19 CL - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.1/NEWS[NEWS file for the NUT v2.7.1 release] + 2.6.5 2012-08-08 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.5/NEWS[NEWS file for the NUT v2.6.5 release] + 2.6.4 2012-05-31 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.4/NEWS[NEWS file for the NUT v2.6.4 release] + 2.6.3 2012-01-04 AQ - + + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.3/NEWS[NEWS file for the NUT v2.6.3 release] + 2.6.2 2011-09-15 AQ - + + Introduced `nut-scanner` tool and `nut-ipmipsu` driver, + and a new `apcsmart` implementation. + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.2/NEWS[NEWS file for the NUT v2.6.2 release] + 2.6.1 2011-06-01 AQ - + + Introduced `default.*` and `override.*` optional settings in `ups.conf`. + Introduced an `ups.efficiency` report and `outlet.0` special handling. + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.1/NEWS[NEWS file for the NUT v2.6.1 release] + @@ -87,7 +111,8 @@ 2011-01-14 AQ - First release of AsciiDoc documentation for Network UPS Tools (NUT). + First release of AsciiDoc documentation for Network UPS Tools (NUT). + See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.0/NEWS[NEWS file for the NUT v2.6.0 release] From eb80fb10dbb65f98cf1d072bc9f59cb97a8851c6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 10:48:32 +0200 Subject: [PATCH 0966/1232] Revert "docs/docinfo.xml.sh: reference the NEWS file (GitHub URL for interactive PDFs) [#2046]" This reverts commit fa8721d98ee3031daed234d50643074e65a9c3a1 and changes for docinfo.xml.in applying it. Referencing the NEWS files for each release proved problematic: the revremark tag does not expect nested tags (like or even

). Signed-off-by: Jim Klimov --- docs/docinfo.xml.in | 11 ----------- docs/docinfo.xml.sh | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index f0f9453da7..59ffbf3e4e 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -17,7 +17,6 @@ 2022-04-26 JK - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.8.0/NEWS[NEWS file for the NUT v2.8.0 release] @@ -26,7 +25,6 @@ 2016-03-09 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.4/NEWS[NEWS file for the NUT v2.7.4 release] @@ -35,7 +33,6 @@ 2015-04-22 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.3/NEWS[NEWS file for the NUT v2.7.3 release] @@ -44,7 +41,6 @@ 2014-04-17 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.2/NEWS[NEWS file for the NUT v2.7.2 release] @@ -53,7 +49,6 @@ 2013-11-19 CL - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.7.1/NEWS[NEWS file for the NUT v2.7.1 release] @@ -62,7 +57,6 @@ 2012-08-08 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.5/NEWS[NEWS file for the NUT v2.6.5 release] @@ -71,7 +65,6 @@ 2012-05-31 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.4/NEWS[NEWS file for the NUT v2.6.4 release] @@ -80,7 +73,6 @@ 2012-01-04 AQ - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.3/NEWS[NEWS file for the NUT v2.6.3 release] @@ -91,7 +83,6 @@ Introduced `nut-scanner` tool and `nut-ipmipsu` driver, and a new `apcsmart` implementation. - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.2/NEWS[NEWS file for the NUT v2.6.2 release] @@ -102,7 +93,6 @@ Introduced `default.*` and `override.*` optional settings in `ups.conf`. Introduced an `ups.efficiency` report and `outlet.0` special handling. - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.1/NEWS[NEWS file for the NUT v2.6.1 release] @@ -112,7 +102,6 @@ AQ First release of AsciiDoc documentation for Network UPS Tools (NUT). - See also: link:https://raw.githubusercontent.com/networkupstools/nut/v2.6.0/NEWS[NEWS file for the NUT v2.6.0 release] diff --git a/docs/docinfo.xml.sh b/docs/docinfo.xml.sh index 4b732c17a3..bb18d86bd9 100755 --- a/docs/docinfo.xml.sh +++ b/docs/docinfo.xml.sh @@ -24,7 +24,7 @@ generate_tags() { NUT_RELEASER="`git log -1 --pretty=format:'%cn' "${RELTAG}" | tr -d 'a-z '`" # Beware to not use "|" in formatting below! Used for sed magic later. - git log -1 --pretty=tformat:' %n @NUT_RELEASE@%n %cs%n @NUT_RELEASER@%n %n See also: link:https://raw.githubusercontent.com/networkupstools/nut/'"${RELTAG}"'/NEWS[NEWS file for the NUT '"${RELTAG}"' release]%n %n %n' \ + git log -1 --pretty=tformat:' %n @NUT_RELEASE@%n %cs%n @NUT_RELEASER@%n %n %n' \ "${RELTAG}" \ | sed \ -e 's,@NUT_RELEASE@,'"${NUT_RELEASE}"',' \ From 43fb146f1bd3ee203789d684d5f021e13fc575bd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 12:13:32 +0200 Subject: [PATCH 0967/1232] docs/docinfo.xml.in: populate remaining "refremark" fields up to (prospective) NUT v2.8.1 release [#2046] Signed-off-by: Jim Klimov --- docs/docinfo.xml.in | 63 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/docs/docinfo.xml.in b/docs/docinfo.xml.in index 59ffbf3e4e..026db780c0 100644 --- a/docs/docinfo.xml.in +++ b/docs/docinfo.xml.in @@ -10,13 +10,42 @@ - + + + 2.8.1 + TBD + JK + + Some changes to API, docs and recipes, in particular to simplify local + builds and tests (e.g. to help end-users check if current NUT codebase + trunk has already fixed an issue they see with a packaged installation). + Revived NUT for Windows effort, further improved other OS integrations. + NUT became reference for "UPS management protocol", Informational RFC 9271. + Documentation files refactored to ease maintenance. + More drivers and new driver categories introduced. + + + 2.8.0 2022-04-26 JK + Change of maintainer. + Many changes to API, docs (both style and content), and recipes, + with a stress on non-regression test-ability, run-time debug-ability, + general codebase maintainability, as well as OS integrations (notably + nut-driver-enumerator for systemd and SMF service instance maintenance). + Added a lot in area of CI support and documented pre-requisite package + lists for numerous platforms, and CI agent set-up. Added libusb-1.x + support and many new driver categories (and drivers), and daisychain + device connection support. Instant commands enhanced with TRACKING to + enable protocol-based waiting for completion of a particular INSTCMD + or SET operation. @@ -25,6 +54,10 @@ 2016-03-09 AQ + NUT variables namespace updated, in particular for outlet groups, + alarms and thresholds, ATS devices, and battery.charger.status to + supersede CHRG and DISCHRG flags published in ups.status readings. + NUT network protocol extended with NUMBER type; some API changes. @@ -33,6 +66,9 @@ 2015-04-22 AQ + Documentation revised, including some API changes. + Added NUT DDL links. + NUT variables namespace updated. @@ -41,6 +77,9 @@ 2014-04-17 AQ + The nut-website project was offloaded into a separate repository. + FreeDesktop HAL support was removed (obsoleted in GNOME consumer). + Introduced nutdrv_atcl_usb driver. @@ -49,6 +88,14 @@ 2013-11-19 CL + NUT source codebase migrated from SVN to Git (and from Debian + infrastructure to GitHub source code hosting). jNut binding + split into a separate project. Introduced libnutclient (C++ + binding), al175, apcupsd-ups and nutdrv_qx drivers, Mozilla + NSS support for simpler licensing than OpenSSL, and a newer + apcsmart implementation. + Documentation support enhanced with a spell checker, contents + massively updated to reflect project changes. @@ -57,6 +104,8 @@ 2012-08-08 AQ + New macosx-ups driver, new implementation of mge-shut driver. + NUT variables namespace updated. Docs cleaned up and revised. @@ -65,6 +114,9 @@ 2012-05-31 AQ + New NUT network protocol commands (LIST CLIENTS, LIST RANGE and + NETVER), and socket protocol commands (ADDRANGE, DELRANGE). + NUT variables namespace updated. Introduced nut-recorder tool. @@ -73,6 +125,7 @@ 2012-01-04 AQ + No substantial changes to documentation. @@ -81,8 +134,8 @@ 2011-09-15 AQ - Introduced `nut-scanner` tool and `nut-ipmipsu` driver, - and a new `apcsmart` implementation. + Introduced nut-scanner tool and nut-ipmipsu driver, + systemd support, and a new apcsmart implementation. @@ -91,8 +144,8 @@ 2011-06-01 AQ - Introduced `default.*` and `override.*` optional settings in `ups.conf`. - Introduced an `ups.efficiency` report and `outlet.0` special handling. + Introduced default.* and override.* optional settings in ups.conf, + an ups.efficiency report, and outlet.0 special handling. From f858be317585e07024e065c50057ba25708b1496 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 16:51:41 +0200 Subject: [PATCH 0968/1232] UPGRADING: suggest --enable-option-checking=fatal for packagers Signed-off-by: Jim Klimov --- UPGRADING | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UPGRADING b/UPGRADING index d29edea18b..9a6ec63626 100644 --- a/UPGRADING +++ b/UPGRADING @@ -13,6 +13,10 @@ explicitly for items not supported on your platform, so you do not miss out on new NUT features as they come with new releases. Some may require that you update your build environment with new third-party dependencies, so a broken build of a new NUT release would let you know how to act. ++ +This is a good time to point out that for stricter packaging systems, it may +be beneficial to add `--enable-option-checking=fatal` to the `./configure` +command line, in order to quickly pick up any other removed option flags. Changes from 2.8.0 to 2.8.1 --------------------------- From 83f3d8b18143baea8da0584ab11f3a4f59f56738 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 13:32:02 +0200 Subject: [PATCH 0969/1232] Rename asciidoc-ready documentation sources to *.adoc [#1953 et al] Follows up from #226, #669 and facilitates #1953 Signed-off-by: Jim Klimov --- .editorconfig | 2 +- .gitignore | 3 +++ INSTALL.nut => INSTALL.nut.adoc | 0 Makefile.am | 2 +- TODO => TODO.adoc | 0 UPGRADING => UPGRADING.adoc | 0 docs/Makefile.am | 22 ++++++++++++++++------ docs/developer-guide.txt | 8 ++++---- docs/nut.dict | 3 ++- docs/security.txt | 2 +- docs/user-manual.txt | 2 +- lib/.gitignore | 1 + lib/Makefile.am | 3 ++- lib/{README => README.adoc} | 0 scripts/Makefile.am | 1 - scripts/augeas/.gitignore | 1 + scripts/augeas/Makefile.am | 4 ++-- scripts/augeas/{README => README.adoc} | 0 scripts/ufw/.gitignore | 1 + scripts/ufw/Makefile.am | 4 +++- scripts/ufw/{README => README.adoc} | 0 tools/nut-scanner/.gitignore | 1 + tools/nut-scanner/Makefile.am | 3 ++- tools/nut-scanner/{README => README.adoc} | 0 24 files changed, 42 insertions(+), 21 deletions(-) rename INSTALL.nut => INSTALL.nut.adoc (100%) rename TODO => TODO.adoc (100%) rename UPGRADING => UPGRADING.adoc (100%) rename lib/{README => README.adoc} (100%) rename scripts/augeas/{README => README.adoc} (100%) rename scripts/ufw/{README => README.adoc} (100%) rename tools/nut-scanner/{README => README.adoc} (100%) diff --git a/.editorconfig b/.editorconfig index 93c3ce8293..fb640f2fd6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -52,7 +52,7 @@ line_comment = dnl max_line_length = 76 line_comment = # -[*.txt{,.in},AUTHORS,COPYING,INSTALL.nut,MAINTAINERS,NEWS,README,TODO,UPGRADING] +[*.txt{,.in},*.adoc{,.in},AUTHORS,COPYING,INSTALL.nut,MAINTAINERS,NEWS,README,TODO,UPGRADING] max_line_length = 76 indent_style = space indent_size = 4 diff --git a/.gitignore b/.gitignore index 76342cad80..406fa4bd19 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ Makefile.in /cscope.* /depcomp /INSTALL +/INSTALL.nut +/TODO +/UPGRADING /install-sh /libtool /ltmain.sh diff --git a/INSTALL.nut b/INSTALL.nut.adoc similarity index 100% rename from INSTALL.nut rename to INSTALL.nut.adoc diff --git a/Makefile.am b/Makefile.am index 1b632c97f8..72806a800f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,7 @@ libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status libtool # COPYING is included automatically. -EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING +EXTRA_DIST = INSTALL.nut.adoc LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING.adoc TODO.adoc # Tarballs created by `make dist` include the `configure.ac` and `m4/*` sources # but lack NUT magic logic to recreate the `configure` script if someone would diff --git a/TODO b/TODO.adoc similarity index 100% rename from TODO rename to TODO.adoc diff --git a/UPGRADING b/UPGRADING.adoc similarity index 100% rename from UPGRADING rename to UPGRADING.adoc diff --git a/docs/Makefile.am b/docs/Makefile.am index f07eeb9485..4c436a634b 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -140,6 +140,7 @@ man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp +CLEANFILES += ../INSTALL.nut ../UPGRADING # Dirs to clean clean-local: @@ -148,10 +149,17 @@ clean-local: ### TODO: automatic dependency generation # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ - ../INSTALL.nut ../UPGRADING ../TODO ../scripts/ufw/README + ../INSTALL.nut ../UPGRADING \ + ../TODO.adoc ../scripts/ufw/README.adoc FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ - ../scripts/augeas/README ../TODO ../lib/README \ - ../tools/nut-scanner/README + ../scripts/augeas/README.adoc ../TODO.adoc \ + ../lib/README.adoc \ + ../tools/nut-scanner/README.adoc + +../INSTALL.nut: ../INSTALL.nut.adoc +../UPGRADING: ../UPGRADING.adoc + @echo " DOC-ASCIIDOC $< => $@" + @cat "$<" > "$@" user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) @@ -271,9 +279,11 @@ if HAVE_ASPELL # its spelling (or errors in that) are not fixable and thus irrelevant. # Similarly for the ../INSTALL file that is prepared by autoconf and not # tracked as a source file by NUT Git repository. -SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../INSTALL.nut ../UPGRADING ../NEWS \ - ../TODO ../scripts/ufw/README ../scripts/augeas/README ../lib/README \ - ../tools/nut-scanner/README \ +SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../NEWS \ + ../INSTALL.nut.adoc ../UPGRADING.adoc \ + ../TODO.adoc ../scripts/ufw/README.adoc \ + ../scripts/augeas/README.adoc ../lib/README.adoc \ + ../tools/nut-scanner/README.adoc \ ../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3 ../LICENSE-DCO # Directory SPELLCHECK_SRC files are relative to. Overriden by other Makefiles. diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 6b0090edc0..18936a960b 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -38,12 +38,12 @@ include::sock-protocol.txt[] [[augeas]] -include::../scripts/augeas/README[] +include::../scripts/augeas/README.adoc[] [[devscan]] -include::../tools/nut-scanner/README[] +include::../tools/nut-scanner/README.adoc[] [[new-clients]] @@ -151,7 +151,7 @@ include::macros.txt[] [[roadmap]] -include::../TODO[] +include::../TODO.adoc[] [[nut-names]] @@ -170,4 +170,4 @@ include::daisychain.txt[] Appendix C: NUT libraries complementary information =================================================== -include::../lib/README[] +include::../lib/README.adoc[] diff --git a/docs/nut.dict b/docs/nut.dict index 1b2b243c79..dc8e864487 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3213 utf-8 +personal_ws-1.1 en 3214 utf-8 AAS ABI ACFAIL @@ -1467,6 +1467,7 @@ adkorte adm admin's adminbox +adoc advorder ae aec diff --git a/docs/security.txt b/docs/security.txt index a6594885fd..92673eb86e 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -265,7 +265,7 @@ You should use this to restrict network access. [[UFW]] -include::../scripts/ufw/README[] +include::../scripts/ufw/README.adoc[] [[TCP_Wrappers]] TCP Wrappers diff --git a/docs/user-manual.txt b/docs/user-manual.txt index 4109b9629f..aa7817fad1 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -81,7 +81,7 @@ include::download.txt[] [[_installation_instructions]] -include::../INSTALL.nut[] +include::../INSTALL.nut.adoc[] [[Configuration_notes]] diff --git a/lib/.gitignore b/lib/.gitignore index 466c02e952..2c9f306f9b 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -3,3 +3,4 @@ /libnutscan.pc /libupsclient-config /libupsclient.pc +/README diff --git a/lib/Makefile.am b/lib/Makefile.am index f4d36ccc2a..5e1478dfe8 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,5 @@ # Network UPS Tools: lib +EXTRA_DIST = README.adoc if WITH_DEV if WITH_PKG_CONFIG @@ -8,5 +9,5 @@ else endif endif -CLEANFILES = *-spellchecked +CLEANFILES = *-spellchecked README MAINTAINERCLEANFILES = Makefile.in .dirstamp diff --git a/lib/README b/lib/README.adoc similarity index 100% rename from lib/README rename to lib/README.adoc diff --git a/scripts/Makefile.am b/scripts/Makefile.am index c87559b597..6113a2b3f5 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -18,7 +18,6 @@ EXTRA_DIST = README \ Solaris8/S99upsmon \ subdriver/gen-usbhid-subdriver.sh \ subdriver/gen-snmp-subdriver.sh \ - ufw/README \ upower/95-upower-hid.hwdb \ upower/95-upower-hid.rules \ Windows/halt.c \ diff --git a/scripts/augeas/.gitignore b/scripts/augeas/.gitignore index 44960455a2..0a87d83815 100644 --- a/scripts/augeas/.gitignore +++ b/scripts/augeas/.gitignore @@ -2,3 +2,4 @@ /nutupsconf.aug.in /nutupsconf.aug.in.AUTOGEN_WITHOUT /gen-nutupsconf-aug.py +/README diff --git a/scripts/augeas/Makefile.am b/scripts/augeas/Makefile.am index 46282e869f..b93033ee5b 100644 --- a/scripts/augeas/Makefile.am +++ b/scripts/augeas/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = gen-nutupsconf-aug.py.in nutupsconf.aug.tpl \ - README tests/test_nut.aug + README.adoc tests/test_nut.aug PYTHON = @PYTHON@ @@ -38,7 +38,7 @@ if WITH_AUGLENS endif MAINTAINERCLEANFILES = Makefile.in .dirstamp -CLEANFILES = *-spellchecked +CLEANFILES = *-spellchecked README # Can be re-generated by configure script and/or make: DISTCLEANFILES = gen-nutupsconf-aug.py diff --git a/scripts/augeas/README b/scripts/augeas/README.adoc similarity index 100% rename from scripts/augeas/README rename to scripts/augeas/README.adoc diff --git a/scripts/ufw/.gitignore b/scripts/ufw/.gitignore index c56f2fa8f4..999163b622 100644 --- a/scripts/ufw/.gitignore +++ b/scripts/ufw/.gitignore @@ -1 +1,2 @@ /nut.ufw.profile +/README diff --git a/scripts/ufw/Makefile.am b/scripts/ufw/Makefile.am index dc72ff3b89..eb6476c94c 100644 --- a/scripts/ufw/Makefile.am +++ b/scripts/ufw/Makefile.am @@ -1,2 +1,4 @@ +EXTRA_DIST = README.adoc nut.ufw.profile.in + MAINTAINERCLEANFILES = Makefile.in .dirstamp -CLEANFILES = *-spellchecked +CLEANFILES = *-spellchecked README diff --git a/scripts/ufw/README b/scripts/ufw/README.adoc similarity index 100% rename from scripts/ufw/README rename to scripts/ufw/README.adoc diff --git a/tools/nut-scanner/.gitignore b/tools/nut-scanner/.gitignore index 393712ae49..9ac9a1ee99 100644 --- a/tools/nut-scanner/.gitignore +++ b/tools/nut-scanner/.gitignore @@ -3,3 +3,4 @@ /nutscan-usb.h /serial.c /bcmxcp_ser.c +/README diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 9a1ad343a7..a79dd0bc6f 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -8,6 +8,7 @@ NUT_SCANNER_DEPS = $(NUT_SCANNER_DEPS_H) $(NUT_SCANNER_DEPS_C) BUILT_SOURCES = $(NUT_SCANNER_DEPS) CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = README.adoc # 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) @@ -143,7 +144,7 @@ endif dummy: -CLEANFILES += *-spellchecked +CLEANFILES += *-spellchecked README MAINTAINERCLEANFILES = Makefile.in .dirstamp # NOTE: Do not clean ".deps" in SUBDIRS of the main project, diff --git a/tools/nut-scanner/README b/tools/nut-scanner/README.adoc similarity index 100% rename from tools/nut-scanner/README rename to tools/nut-scanner/README.adoc From d151fe9aa4456e50fe869c93817be61dd47ba553 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 16:51:04 +0200 Subject: [PATCH 0970/1232] docs/Makefile.am: implement DOCBUILD_FILTER_GITHUB_LINKS [#1953] Signed-off-by: Jim Klimov --- docs/Makefile.am | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 4c436a634b..d2c7006eb8 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -146,7 +146,34 @@ CLEANFILES += ../INSTALL.nut ../UPGRADING clean-local: $(AM_V_at)rm -rf *.chunked *.bak tmp -### TODO: automatic dependency generation +### TODO: general automatic dependency generation + +# Prepare text files (currently a manually tracked list) +# with known presence of GitHub links to convert them from +# short notation into asciidoc link markup +# before rendering into HTML/PDF. +# Work around some documents that have originally included +# the asciidoc markup (use double-hash to avoid conversion). +DOCBUILD_FILTER_GITHUB_LINKS = { \ + echo " DOC-ASCIIDOC-GITHUB-LINKS Parsing GitHub link patterns $< => $@"; \ + cat "$<" | $(SED) \ + -e 's%\(link:https*://github.com/networkupstools/[a-zA-Z0-9./-]*/[1-9][0-9]*/*\[[^]]*\)\#\([1-9][0-9]*\)%\1\#\#\2%g' \ + -e 's%\(issue\) *\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/nut/issues/\2[\1 \#\#\2]\3%g' \ + -e 's%\(PR\|pull request\) *\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/nut/pull/\2[\1 \#\#\2]\3%g' \ + -e 's%\([[ ,]\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%\1link:https://github.com/networkupstools/nut/issues/\2[\#\#\2]\3%g' \ + -e 's%\(issue\) networkupstools/\([^ ][^ ]*\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/\2/issues/\3[\1 \2\#\#\3]\4%g' \ + -e 's%\(PR\|pull request\) *networkupstools/\([^ ][^ ]*\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/\2/pull/\3[\1 \2\#\#\3]\4%g' \ + -e 's%\([[ ,]\)networkupstools/\([^ ][^ ]*\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%\1link:https://github.com/networkupstools/\2/issues/\3[\2\#\#\3]\4%g' \ + -e 's%\#\(\#[1-9][0-9]*\)%\1%g' \ + > "$@" \ +; } + +../INSTALL.nut: ../INSTALL.nut.adoc + @$(DOCBUILD_FILTER_GITHUB_LINKS) + +../UPGRADING: ../UPGRADING.adoc + @$(DOCBUILD_FILTER_GITHUB_LINKS) + # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ ../INSTALL.nut ../UPGRADING \ @@ -156,11 +183,6 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ ../lib/README.adoc \ ../tools/nut-scanner/README.adoc -../INSTALL.nut: ../INSTALL.nut.adoc -../UPGRADING: ../UPGRADING.adoc - @echo " DOC-ASCIIDOC $< => $@" - @cat "$<" > "$@" - user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf From 033167fef9ce148e4680e2c1542d8ad5f8f7c7dc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 17:13:07 +0200 Subject: [PATCH 0971/1232] Convert NEWS => NEWS.adoc (basic section structure) and render it as release-notes (HTML, PDF) [#1953] Signed-off-by: Jim Klimov --- Makefile.am | 3 +- NEWS => NEWS.adoc | 167 +++++++++++++++++++++++++++++----------------- autogen.sh | 4 ++ docs/Makefile.am | 11 ++- 4 files changed, 122 insertions(+), 63 deletions(-) rename NEWS => NEWS.adoc (96%) diff --git a/Makefile.am b/Makefile.am index 72806a800f..e88d9644a8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,7 @@ libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status libtool # COPYING is included automatically. -EXTRA_DIST = INSTALL.nut.adoc LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING.adoc TODO.adoc +EXTRA_DIST = INSTALL.nut.adoc LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING.adoc TODO.adoc NEWS.adoc # Tarballs created by `make dist` include the `configure.ac` and `m4/*` sources # but lack NUT magic logic to recreate the `configure` script if someone would @@ -133,6 +133,7 @@ spellcheck spellcheck-interactive: # such as PDF generators, so it should only be called at developer's # discretion, choice and risk. The "check-man" targets covers source # texts, man pages and HTML rendering of man pages, as enabled by tools. +INSTALL.nut UPGRADING NEWS \ doc spellcheck-sortdict \ all-docs check-docs \ man all-man man-man check-man man-html all-html: diff --git a/NEWS b/NEWS.adoc similarity index 96% rename from NEWS rename to NEWS.adoc index fe84ac69fc..7047d0d107 100644 --- a/NEWS +++ b/NEWS.adoc @@ -1,11 +1,17 @@ -If you're upgrading from an earlier version, see the UPGRADING file. +ifdef::txt[] +Release notes (detailed NUT project news) +========================================= +endif::txt[] + +If you're upgrading from an earlier version, see the linkdoc:UPGRADING.adoc[] file. 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.3 - what's new since 2.8.2: + +PLANNED: Release notes for NUT 2.8.3 - what's new since 2.8.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://github.com/networkupstools/nut/milestone/9 @@ -13,8 +19,9 @@ https://github.com/networkupstools/nut/milestone/9 the driver binaries to be built once and data mappings to be loaded and modernized on the fly [Ported from 42ITy project] ---------------------------------------------------------------------------- -PLANNED: Release notes for NUT 2.8.2 - what's new since 2.8.1: + +PLANNED: Release notes for NUT 2.8.2 - what's new since 2.8.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://github.com/networkupstools/nut/milestone/10 @@ -29,8 +36,9 @@ https://github.com/networkupstools/nut/milestone/10 - (expected) Bug fixes for fallout possible due to "fightwarn" effort in 2.8.0 ---------------------------------------------------------------------------- -PLANNED: Release notes for NUT 2.8.1 - what's new since 2.8.0: + +PLANNED: Release notes for NUT 2.8.1 - what's new since 2.8.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://github.com/networkupstools/nut/milestone/8 @@ -408,8 +416,9 @@ and a `driver.killpower` instant command (for safety, must be unlocked by recipes published on GitHub at https://github.com/rgc2000/NutClient-ESXi [#1961] ---------------------------------------------------------------------------- -Release notes for NUT 2.8.0 - what's new since 2.7.4: + +Release notes for NUT 2.8.0 - what's new since 2.7.4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NOTE: Earlier discussions (mailing list threads, GitHub issues, etc.) could refer to this change set (too long in the making) as NUT 2.7.5. @@ -813,8 +822,9 @@ refer to this change set (too long in the making) as NUT 2.7.5. - As usual, more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.7.4 - what's new since 2.7.3: + +Release notes for NUT 2.7.4 - what's new since 2.7.3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - New class of device supported: ATS - Automatic Transfer Switch are now supported in NUT. Eaton ATS are supported, and APC ones should be too. Users @@ -1001,8 +1011,9 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2: Tripp Lite OMNIVSINT800 Voltronic Power Apex 1KVA and Imperial 1KVA ---------------------------------------------------------------------------- -Release notes for NUT 2.7.2 - what's new since 2.7.1: + +Release notes for NUT 2.7.2 - what's new since 2.7.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This release is the second interim release of the 2.7 testing series. @@ -1046,8 +1057,11 @@ Release notes for NUT 2.7.2 - what's new since 2.7.1: - As usual, more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.7.1 - what's new since 2.6.5: + +Release notes for NUT 2.7.1 - what's new since 2.6.5 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NOTE: There was no public NUT 2.7.0 release. - This release is an interim release, part of the testing series, and the first release after the transition from Subversion to Git. @@ -1123,8 +1137,9 @@ Release notes for NUT 2.7.1 - what's new since 2.6.5: support. Also fixed mappings for upsBypassVoltage, upsBypassCurrent, and upsBypassPower in three-phase IETF MIB. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.5 - what's new since 2.6.4: + +Release notes for NUT 2.6.5 - what's new since 2.6.4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This release fixes an important regression in upssched: any upssched.conf command that takes a second argument resulted in @@ -1172,8 +1187,9 @@ Release notes for NUT 2.6.5 - what's new since 2.6.4: - more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.4 - what's new since 2.6.3: + +Release notes for NUT 2.6.4 - what's new since 2.6.3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This release Fix an important vulnerability in upsd (CVE-2012-2944: upsd can be remotely crashed) @@ -1291,8 +1307,9 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3: - more bugfixes, cleanup and improvements, on both source code and documentation, with a good bunch from Greg A. Woods. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.3 - what's new since 2.6.2: + +Release notes for NUT 2.6.3 - what's new since 2.6.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - nut-scanner is now more portable, and provides more coherent option names. IPMI support has also been added, to discover local power supplies. @@ -1342,8 +1359,9 @@ Release notes for NUT 2.6.3 - what's new since 2.6.2: - more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.2 - what's new since 2.6.1: + +Release notes for NUT 2.6.2 - what's new since 2.6.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - NUT can now monitor power supply units (PSU) in servers, through IPMI, using the new experimental 'nut-ipmipsu' driver. Users are encouraged to test it, @@ -1415,8 +1433,9 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1: - Finally, after years of dedication to NUT, Arjen de Korte is now retired. Sincere thanks to you Arjen from us all. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.1 - what's new since 2.6.0: + +Release notes for NUT 2.6.1 - what's new since 2.6.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - the various recent USB regressions have been definitely fixed. @@ -1460,8 +1479,11 @@ Release notes for NUT 2.6.1 - what's new since 2.6.0: - more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.6.0 - what's new since 2.4.3: + +Release notes for NUT 2.6.0 - what's new since 2.4.3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NOTE: Per original semantic versioning, there were no public NUT 2.5.x releases. - the main focus of this release is the complete documentation revamping, using AsciiDoc. This includes a new website, user manual, developer guide, @@ -1521,13 +1543,15 @@ Release notes for NUT 2.6.0 - what's new since 2.4.3: - many bugfixes, cleanup and improvements. ---------------------------------------------------------------------------- -Release notes for NUT 2.4.3 - what's new since 2.4.2: + +Release notes for NUT 2.4.3 - what's new since 2.4.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - this is a bugfix release that only solves the regression on IPv6 activation. ---------------------------------------------------------------------------- -Release notes for NUT 2.4.2 - what's new since 2.4.1: + +Release notes for NUT 2.4.2 - what's new since 2.4.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - the general USB support has been vastly improved, including many bug fixes, better OS support, new features and devices. @@ -1564,8 +1588,9 @@ Release notes for NUT 2.4.2 - what's new since 2.4.1: Tripp-Lite INTERNETOFFICE700, SMART700USB and ECO550UPS; UPSonic DS-800 (USB). ---------------------------------------------------------------------------- -Release notes for NUT 2.4.1 - what's new since 2.4.0: + +Release notes for NUT 2.4.1 - what's new since 2.4.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - the microdowell driver has appeared to support various MicroDowell Enterprise units (see the "new devices" list below). @@ -1580,8 +1605,11 @@ Release notes for NUT 2.4.1 - what's new since 2.4.0: "make clean" target and the wrongly removed generated USB files. This broke further configure call. ---------------------------------------------------------------------------- -Release notes for NUT 2.4.0 - what's new since 2.2.2: + +Release notes for NUT 2.4.0 - what's new since 2.2.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NOTE: Per original semantic versioning, there were no public NUT 2.3.x releases. - preliminary support for Power Distribution Units (PDUs): NUT now support PDUs, either natively (ie using NUT snmp-ups driver), or through a binding to @@ -1631,8 +1659,9 @@ Release notes for NUT 2.4.0 - what's new since 2.2.2: - tons of bugfixes, cleanup and improvements to make NUT stronger than ever! ---------------------------------------------------------------------------- -Release notes for NUT 2.2.2 - what's new since 2.2.1: + +Release notes for NUT 2.2.2 - what's new since 2.2.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - support for new devices: APC BACK-UPS XS LCD, Atlantis Land, Mustek Powermust Office 650, Oneac XAU models, Powerware PW5115 and @@ -1667,8 +1696,9 @@ Release notes for NUT 2.2.2 - what's new since 2.2.1: - many changes, cleanup and fixes to the NUT core and various drivers. ---------------------------------------------------------------------------- -Release notes for NUT 2.2.1 - what's new since 2.2.0: + +Release notes for NUT 2.2.1 - what's new since 2.2.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - support for new devices: all MGE Office Protection Systems units, Advice TopGuard 2000, Belkin F6H375-USB, Dynamix UPS1700D, Effekta RM2000MH, @@ -1689,8 +1719,11 @@ Release notes for NUT 2.2.1 - what's new since 2.2.0: the upsclient pkg-config file has been fixed, and the upsclient.h file allows older NUT clients to continue using the UPSCONN structure. ---------------------------------------------------------------------------- -Release notes for NUT 2.2.0 - what's new since 2.0.5: + +Release notes for NUT 2.2.0 - what's new since 2.0.5 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NOTE: Per original semantic versioning, there were no public NUT 2.1.x releases. - The new build infrastructure, using automake, is now used. This has major impact on the compilation and installation procedures, @@ -1731,8 +1764,9 @@ Release notes for NUT 2.2.0 - what's new since 2.0.5: - more generally, the NUT core and documentation, including the manpages, have been improved and updated. ---------------------------------------------------------------------------- -Release notes for NUT 2.0.5 - what's new since 2.0.4: + +Release notes for NUT 2.0.5 - what's new since 2.0.4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This release is a backport of the development version. Many changes have already been backported previously. Thus it is more a @@ -1766,8 +1800,9 @@ Release notes for NUT 2.0.5 - what's new since 2.0.4: - added HTML interface for access to CGI scripts ---------------------------------------------------------------------------- -Release notes for NUT 2.0.4 - what's new since 2.0.3: + +Release notes for NUT 2.0.4 - what's new since 2.0.3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The newhidups critical bug (segmentation fault) has been fixed. It has also received some more care, like bugfixes and new models support and @@ -1807,8 +1842,9 @@ Release notes for NUT 2.0.4 - what's new since 2.0.3: cpsups, tripplite_usb and the FAQ. [Arjen de Korte and Charles Lepple] ---------------------------------------------------------------------------- -Release notes for NUT 2.0.3 - what's new since 2.0.2: + +Release notes for NUT 2.0.3 - what's new since 2.0.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The recent and major newhidups changes have been backported from the Development tree. It now: @@ -1865,8 +1901,9 @@ Release notes for NUT 2.0.3 - what's new since 2.0.2: - The snmp-ups driver has corrected the problem when exposing certain time data. ---------------------------------------------------------------------------- -Release notes for NUT 2.0.2 - what's new since 2.0.1: + +Release notes for NUT 2.0.2 - what's new since 2.0.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - the newhidups USB driver has been improved a lot and is no more experimental. It also now has a basic APC support, which will @@ -1921,8 +1958,9 @@ Release notes for NUT 2.0.2 - what's new since 2.0.1: - The tripplite driver has fixed a battery charge bug [Cedric Tefft] ---------------------------------------------------------------------------- -Release notes for NUT 2.0.1 - what's new since 2.0.0: + +Release notes for NUT 2.0.1 - what's new since 2.0.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The bestuferrups driver has been forked into the new bestfcom driver which has better handling of the inverter status alarm messages and @@ -2023,8 +2061,9 @@ Release notes for NUT 2.0.1 - what's new since 2.0.0: snmp-ups and upsd. [Ulf Harnhammar] ---------------------------------------------------------------------------- -Release notes for NUT 2.0.0 - what's new since 1.4.x: + +Release notes for NUT 2.0.0 - what's new since 1.4.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The new naming scheme for variables and commands (introduced in 1.4) is now mandatory. The 1.4 tree supported both the old (STATUS) and @@ -2147,8 +2186,9 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x: code. Any failure during a requested operation will result in a nonzero value (specifically EXIT_FAILURE). ---------------------------------------------------------------------------- -Release notes for NUT 1.4.0 - what's new since 1.2.x: + +Release notes for NUT 1.4.0 - what's new since 1.2.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The drivers and upsd now communicate over Unix domain sockets instead of state files, shared memory, or state files with mmap. This change @@ -2381,8 +2421,9 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x: compiles on some systems. [Petter Reinholdtsen] ---------------------------------------------------------------------------- -Release notes for NUT 1.2.2 - what's new since 1.2.1: + +Release notes for NUT 1.2.2 - what's new since 1.2.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The snmp-ups driver has been upgraded and expanded. It now supports multiple MIBs, meaning it can handle RFC 1628, APCC, and MGE @@ -2469,9 +2510,9 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1: depending on what areas were accessed. [Patrik Schindler] ---------------------------------------------------------------------------- -Release notes for NUT 1.2.1 - what's new since 1.2.0: +Release notes for NUT 1.2.1 - what's new since 1.2.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The sms driver is back, with support for Microlink Manager III hardware. [Marcio Gomes] @@ -2495,4 +2536,10 @@ Release notes for NUT 1.2.1 - what's new since 1.2.0: - Shutdowns on FreeBSD using the genericups driver should work again. [Petri Riihikallio] ---------------------------------------------------------------------------- + +Historic releases +~~~~~~~~~~~~~~~~~ + +More ancient history is not covered in detail here. + +You can see linkdoc:docs/history.txt[] for more details. diff --git a/autogen.sh b/autogen.sh index b15a2e37cd..941c1215f6 100755 --- a/autogen.sh +++ b/autogen.sh @@ -147,6 +147,10 @@ if ( command -v dos2unix ) 2>/dev/null >/dev/null ; then fi fi >&2 +# Required by autoconf for non-"foreign" projects; +# is tracked as a NEWS.adoc for us however. +[ -f NEWS ] || { echo "See NEWS.adoc for actual contents" > NEWS; } + echo "Calling autoreconf..." AUTOTOOL_RES=0 if $DEBUG ; then diff --git a/docs/Makefile.am b/docs/Makefile.am index d2c7006eb8..f470db00bd 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -56,6 +56,7 @@ EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ ASCIIDOC_HTML_SINGLE = user-manual.html \ developer-guide.html \ packager-guide.html \ + release-notes.html \ solaris-usb.html \ cables.html \ FAQ.html @@ -63,6 +64,7 @@ ASCIIDOC_HTML_SINGLE = user-manual.html \ ASCIIDOC_HTML_CHUNKED = user-manual.chunked \ developer-guide.chunked \ packager-guide.chunked \ + release-notes.chunked \ solaris-usb.chunked \ cables.chunked \ FAQ.chunked @@ -70,6 +72,7 @@ ASCIIDOC_HTML_CHUNKED = user-manual.chunked \ ASCIIDOC_PDF = user-manual.pdf \ developer-guide.pdf \ packager-guide.pdf \ + release-notes.pdf \ solaris-usb.pdf \ cables.pdf \ FAQ.pdf @@ -140,7 +143,7 @@ man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp -CLEANFILES += ../INSTALL.nut ../UPGRADING +CLEANFILES += ../INSTALL.nut ../UPGRADING ../NEWS # Dirs to clean clean-local: @@ -174,6 +177,9 @@ DOCBUILD_FILTER_GITHUB_LINKS = { \ ../UPGRADING: ../UPGRADING.adoc @$(DOCBUILD_FILTER_GITHUB_LINKS) +../NEWS: ../NEWS.adoc + @$(DOCBUILD_FILTER_GITHUB_LINKS) + # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ ../INSTALL.nut ../UPGRADING \ @@ -186,6 +192,7 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf +release-notes.html release-notes.chunked release-notes.pdf: ../NEWS asciidoc.conf solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf # Note: without the "-v", asciidoc (circa 8.6.2) sometimes hangs when @@ -301,7 +308,7 @@ if HAVE_ASPELL # its spelling (or errors in that) are not fixable and thus irrelevant. # Similarly for the ../INSTALL file that is prepared by autoconf and not # tracked as a source file by NUT Git repository. -SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../NEWS \ +SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../NEWS.adoc \ ../INSTALL.nut.adoc ../UPGRADING.adoc \ ../TODO.adoc ../scripts/ufw/README.adoc \ ../scripts/augeas/README.adoc ../lib/README.adoc \ From 8b376a18c192ec8290382ecd8ea771ebdd0c74bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 18:41:32 +0200 Subject: [PATCH 0972/1232] Use *.adoc-parsed extension for post-processed asciidoc files used in rendering to HTML/PDF artifacts [#1953] Signed-off-by: Jim Klimov --- .gitignore | 1 + Makefile.am | 6 ++-- NEWS.adoc | 69 ++++++++++++++++++++++---------------------- docs/Makefile.am | 9 ++---- docs/user-manual.txt | 4 +-- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 406fa4bd19..a038f87a14 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ Makefile.in /missing /test-driver *-spellchecked +*.adoc-parsed /cppcheck*.xml /.ci*.log /.ci*.log.* diff --git a/Makefile.am b/Makefile.am index e88d9644a8..1fd4e564e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,7 @@ distcleancheck: realclean: maintainer-clean # Files made by our targets: -CLEANFILES = *-spellchecked cppcheck*.xml +CLEANFILES = *-spellchecked *.adoc-parsed cppcheck*.xml DISTCLEANFILES = ChangeLog # Most of the files generated by custom rules in the configure script @@ -133,12 +133,14 @@ spellcheck spellcheck-interactive: # such as PDF generators, so it should only be called at developer's # discretion, choice and risk. The "check-man" targets covers source # texts, man pages and HTML rendering of man pages, as enabled by tools. -INSTALL.nut UPGRADING NEWS \ doc spellcheck-sortdict \ all-docs check-docs \ man all-man man-man check-man man-html all-html: cd $(builddir)/docs && $(MAKE) $@ +INSTALL.nut UPGRADING NEWS: + cd $(builddir)/docs && $(MAKE) ../$(@F).adoc-parsed && cp -f ../$(@F).adoc-parsed ../$(@F) + check-NIT check-NIT-devel: cd $(builddir)/tests/NIT && $(MAKE) $@ diff --git a/NEWS.adoc b/NEWS.adoc index 7047d0d107..0309fdcdc1 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -11,7 +11,7 @@ control history for "live" codebase. PLANNED: Release notes for NUT 2.8.3 - what's new since 2.8.2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------------------------- https://github.com/networkupstools/nut/milestone/9 @@ -21,7 +21,7 @@ https://github.com/networkupstools/nut/milestone/9 PLANNED: Release notes for NUT 2.8.2 - what's new since 2.8.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------------------------- https://github.com/networkupstools/nut/milestone/10 @@ -38,7 +38,7 @@ https://github.com/networkupstools/nut/milestone/10 PLANNED: Release notes for NUT 2.8.1 - what's new since 2.8.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------------------------- https://github.com/networkupstools/nut/milestone/8 @@ -418,7 +418,7 @@ and a `driver.killpower` instant command (for safety, must be unlocked by Release notes for NUT 2.8.0 - what's new since 2.7.4 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- NOTE: Earlier discussions (mailing list threads, GitHub issues, etc.) could refer to this change set (too long in the making) as NUT 2.7.5. @@ -824,7 +824,7 @@ refer to this change set (too long in the making) as NUT 2.7.5. Release notes for NUT 2.7.4 - what's new since 2.7.3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - New class of device supported: ATS - Automatic Transfer Switch are now supported in NUT. Eaton ATS are supported, and APC ones should be too. Users @@ -941,8 +941,9 @@ Release notes for NUT 2.7.4 - what's new since 2.7.3 - As usual, more bugfixes, cleanup and improvements, on both source code and documentation. ---------------------------------------------------------------------------- -Release notes for NUT 2.7.3 - what's new since 2.7.2: + +Release notes for NUT 2.7.3 - what's new since 2.7.2 +---------------------------------------------------- - reverted POWERDOWNFLAG to /etc/killpower as in 2.6.5 (packagers may want to put this in another filesystem, though) @@ -1013,7 +1014,7 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2: Release notes for NUT 2.7.2 - what's new since 2.7.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - This release is the second interim release of the 2.7 testing series. @@ -1059,7 +1060,7 @@ Release notes for NUT 2.7.2 - what's new since 2.7.1 Release notes for NUT 2.7.1 - what's new since 2.6.5 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- NOTE: There was no public NUT 2.7.0 release. @@ -1139,7 +1140,7 @@ NOTE: There was no public NUT 2.7.0 release. Release notes for NUT 2.6.5 - what's new since 2.6.4 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - This release fixes an important regression in upssched: any upssched.conf command that takes a second argument resulted in @@ -1189,7 +1190,7 @@ Release notes for NUT 2.6.5 - what's new since 2.6.4 Release notes for NUT 2.6.4 - what's new since 2.6.3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - This release Fix an important vulnerability in upsd (CVE-2012-2944: upsd can be remotely crashed) @@ -1309,7 +1310,7 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3 Release notes for NUT 2.6.3 - what's new since 2.6.2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - nut-scanner is now more portable, and provides more coherent option names. IPMI support has also been added, to discover local power supplies. @@ -1361,7 +1362,7 @@ Release notes for NUT 2.6.3 - what's new since 2.6.2 Release notes for NUT 2.6.2 - what's new since 2.6.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - NUT can now monitor power supply units (PSU) in servers, through IPMI, using the new experimental 'nut-ipmipsu' driver. Users are encouraged to test it, @@ -1435,7 +1436,7 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1 Release notes for NUT 2.6.1 - what's new since 2.6.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - the various recent USB regressions have been definitely fixed. @@ -1481,7 +1482,7 @@ Release notes for NUT 2.6.1 - what's new since 2.6.0 Release notes for NUT 2.6.0 - what's new since 2.4.3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- NOTE: Per original semantic versioning, there were no public NUT 2.5.x releases. @@ -1545,13 +1546,13 @@ NOTE: Per original semantic versioning, there were no public NUT 2.5.x releases. Release notes for NUT 2.4.3 - what's new since 2.4.2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - this is a bugfix release that only solves the regression on IPv6 activation. Release notes for NUT 2.4.2 - what's new since 2.4.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - the general USB support has been vastly improved, including many bug fixes, better OS support, new features and devices. @@ -1590,7 +1591,7 @@ Release notes for NUT 2.4.2 - what's new since 2.4.1 Release notes for NUT 2.4.1 - what's new since 2.4.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - the microdowell driver has appeared to support various MicroDowell Enterprise units (see the "new devices" list below). @@ -1607,7 +1608,7 @@ Release notes for NUT 2.4.1 - what's new since 2.4.0 Release notes for NUT 2.4.0 - what's new since 2.2.2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- NOTE: Per original semantic versioning, there were no public NUT 2.3.x releases. @@ -1661,7 +1662,7 @@ NOTE: Per original semantic versioning, there were no public NUT 2.3.x releases. Release notes for NUT 2.2.2 - what's new since 2.2.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - support for new devices: APC BACK-UPS XS LCD, Atlantis Land, Mustek Powermust Office 650, Oneac XAU models, Powerware PW5115 and @@ -1698,7 +1699,7 @@ Release notes for NUT 2.2.2 - what's new since 2.2.1 Release notes for NUT 2.2.1 - what's new since 2.2.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - support for new devices: all MGE Office Protection Systems units, Advice TopGuard 2000, Belkin F6H375-USB, Dynamix UPS1700D, Effekta RM2000MH, @@ -1721,7 +1722,7 @@ Release notes for NUT 2.2.1 - what's new since 2.2.0 Release notes for NUT 2.2.0 - what's new since 2.0.5 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- NOTE: Per original semantic versioning, there were no public NUT 2.1.x releases. @@ -1766,7 +1767,7 @@ NOTE: Per original semantic versioning, there were no public NUT 2.1.x releases. Release notes for NUT 2.0.5 - what's new since 2.0.4 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- This release is a backport of the development version. Many changes have already been backported previously. Thus it is more a @@ -1802,7 +1803,7 @@ Release notes for NUT 2.0.5 - what's new since 2.0.4 Release notes for NUT 2.0.4 - what's new since 2.0.3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The newhidups critical bug (segmentation fault) has been fixed. It has also received some more care, like bugfixes and new models support and @@ -1844,7 +1845,7 @@ Release notes for NUT 2.0.4 - what's new since 2.0.3 Release notes for NUT 2.0.3 - what's new since 2.0.2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The recent and major newhidups changes have been backported from the Development tree. It now: @@ -1903,7 +1904,7 @@ Release notes for NUT 2.0.3 - what's new since 2.0.2 Release notes for NUT 2.0.2 - what's new since 2.0.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - the newhidups USB driver has been improved a lot and is no more experimental. It also now has a basic APC support, which will @@ -1960,7 +1961,7 @@ Release notes for NUT 2.0.2 - what's new since 2.0.1 Release notes for NUT 2.0.1 - what's new since 2.0.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The bestuferrups driver has been forked into the new bestfcom driver which has better handling of the inverter status alarm messages and @@ -2063,7 +2064,7 @@ Release notes for NUT 2.0.1 - what's new since 2.0.0 Release notes for NUT 2.0.0 - what's new since 1.4.x -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The new naming scheme for variables and commands (introduced in 1.4) is now mandatory. The 1.4 tree supported both the old (STATUS) and @@ -2188,7 +2189,7 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x Release notes for NUT 1.4.0 - what's new since 1.2.x -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The drivers and upsd now communicate over Unix domain sockets instead of state files, shared memory, or state files with mmap. This change @@ -2423,7 +2424,7 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x Release notes for NUT 1.2.2 - what's new since 1.2.1 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The snmp-ups driver has been upgraded and expanded. It now supports multiple MIBs, meaning it can handle RFC 1628, APCC, and MGE @@ -2512,13 +2513,13 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1 Release notes for NUT 1.2.1 - what's new since 1.2.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- - The sms driver is back, with support for Microlink Manager III hardware. [Marcio Gomes] - - Fideltronik Ares Series hardware is now supported as genericups type - 19. [Tomek Orzechowski and Arkadiusz Mikiewicz] + - Fideltronik Ares Series hardware is now supported as genericups + type 19. [Tomek Orzechowski and Arkadiusz Mikiewicz] - The drivers no longer silently drop instant commands or set commands from upsd that happen to get fragmented in transit. @@ -2538,7 +2539,7 @@ Release notes for NUT 1.2.1 - what's new since 1.2.0 Historic releases -~~~~~~~~~~~~~~~~~ +----------------- More ancient history is not covered in detail here. diff --git a/docs/Makefile.am b/docs/Makefile.am index f470db00bd..fd30929cea 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -144,6 +144,7 @@ man: CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp CLEANFILES += ../INSTALL.nut ../UPGRADING ../NEWS +CLEANFILES += ../*.adoc-parsed *.adoc-parsed # Dirs to clean clean-local: @@ -171,18 +172,14 @@ DOCBUILD_FILTER_GITHUB_LINKS = { \ > "$@" \ ; } -../INSTALL.nut: ../INSTALL.nut.adoc +.adoc.adoc-parsed: @$(DOCBUILD_FILTER_GITHUB_LINKS) -../UPGRADING: ../UPGRADING.adoc - @$(DOCBUILD_FILTER_GITHUB_LINKS) -../NEWS: ../NEWS.adoc - @$(DOCBUILD_FILTER_GITHUB_LINKS) # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ - ../INSTALL.nut ../UPGRADING \ + ../INSTALL.nut.adoc-parsed ../UPGRADING.adoc-parsed \ ../TODO.adoc ../scripts/ufw/README.adoc FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ ../scripts/augeas/README.adoc ../TODO.adoc \ diff --git a/docs/user-manual.txt b/docs/user-manual.txt index aa7817fad1..bc66b68148 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -81,7 +81,7 @@ include::download.txt[] [[_installation_instructions]] -include::../INSTALL.nut.adoc[] +include::../INSTALL.nut.adoc-parsed[] [[Configuration_notes]] @@ -185,7 +185,7 @@ include::configure.txt[] Appendix I: Upgrading notes =========================== -include::../UPGRADING[] +include::../UPGRADING.adoc-parsed[] [[Project_History]] From b59797875bfc5c7d14ffcaa4e3aee2a0518ae024 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 18:44:46 +0200 Subject: [PATCH 0973/1232] Introduce buildable (HTML/PDF) release-notes and ChangeLog documents [#1953] Signed-off-by: Jim Klimov --- .gitignore | 1 + NEWS.adoc | 4 ++-- docs/ChangeLog.txt | 21 ++++++++++++++++++++ docs/Makefile.am | 45 +++++++++++++++++++++++++++++++++--------- docs/documentation.txt | 4 ++++ docs/release-notes.txt | 33 +++++++++++++++++++++++++++++++ docs/user-manual.txt | 4 ++-- 7 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 docs/ChangeLog.txt create mode 100644 docs/release-notes.txt diff --git a/.gitignore b/.gitignore index a038f87a14..4e8d64892b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ Makefile.in /ar-lib /autom4te.cache/ /ChangeLog +/ChangeLog.adoc /config.guess /config.log /config.status diff --git a/NEWS.adoc b/NEWS.adoc index 0309fdcdc1..bb8fd0c9b7 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -1,6 +1,6 @@ ifdef::txt[] -Release notes (detailed NUT project news) -========================================= +NUT Release Notes +================= endif::txt[] If you're upgrading from an earlier version, see the linkdoc:UPGRADING.adoc[] file. diff --git a/docs/ChangeLog.txt b/docs/ChangeLog.txt new file mode 100644 index 0000000000..cb351e3c3d --- /dev/null +++ b/docs/ChangeLog.txt @@ -0,0 +1,21 @@ +:titles.underlines: "__","==","--","~~","^^" + +Network UPS Tools Change Log +____________________________ +:Author: NUT_project_community_contributors + +Introduction +============ + +The primary goal of the Network UPS Tools (NUT) project is to provide support +for Power Devices, such as Uninterruptible Power Supplies, Power Distribution +Units and Solar Controllers. + +[[Change_Log]] +Very detailed Change Log +======================== + +This document intends to detail the change log for relatively recent work +(roughly since the source code was tracked in Git). + +include::{builddir}/../ChangeLog.adoc-parsed[] diff --git a/docs/Makefile.am b/docs/Makefile.am index fd30929cea..44a9cd5f56 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -46,7 +46,7 @@ CABLES_IMAGES = images/cables/73-0724.png images/cables/940-0024C.jpg \ ALL_TXT_SRC = nut-names.txt daisychain.txt \ $(USER_MANUAL_DEPS) $(DEVELOPER_GUIDE_DEPS) \ $(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt \ - solaris-usb.txt + release-notes.txt ChangeLog.txt solaris-usb.txt NUT_SPELL_DICT = nut.dict EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ @@ -57,6 +57,7 @@ ASCIIDOC_HTML_SINGLE = user-manual.html \ developer-guide.html \ packager-guide.html \ release-notes.html \ + ChangeLog.html \ solaris-usb.html \ cables.html \ FAQ.html @@ -65,6 +66,7 @@ ASCIIDOC_HTML_CHUNKED = user-manual.chunked \ developer-guide.chunked \ packager-guide.chunked \ release-notes.chunked \ + ChangeLog.chunked \ solaris-usb.chunked \ cables.chunked \ FAQ.chunked @@ -73,6 +75,7 @@ ASCIIDOC_PDF = user-manual.pdf \ developer-guide.pdf \ packager-guide.pdf \ release-notes.pdf \ + ChangeLog.pdf \ solaris-usb.pdf \ cables.pdf \ FAQ.pdf @@ -143,7 +146,7 @@ man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp -CLEANFILES += ../INSTALL.nut ../UPGRADING ../NEWS +CLEANFILES += ../INSTALL.nut ../UPGRADING ../NEWS ../ChangeLog.adoc CLEANFILES += ../*.adoc-parsed *.adoc-parsed # Dirs to clean @@ -158,9 +161,9 @@ clean-local: # before rendering into HTML/PDF. # Work around some documents that have originally included # the asciidoc markup (use double-hash to avoid conversion). + DOCBUILD_FILTER_GITHUB_LINKS = { \ - echo " DOC-ASCIIDOC-GITHUB-LINKS Parsing GitHub link patterns $< => $@"; \ - cat "$<" | $(SED) \ + $(SED) \ -e 's%\(link:https*://github.com/networkupstools/[a-zA-Z0-9./-]*/[1-9][0-9]*/*\[[^]]*\)\#\([1-9][0-9]*\)%\1\#\#\2%g' \ -e 's%\(issue\) *\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/nut/issues/\2[\1 \#\#\2]\3%g' \ -e 's%\(PR\|pull request\) *\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/nut/pull/\2[\1 \#\#\2]\3%g' \ @@ -169,13 +172,34 @@ DOCBUILD_FILTER_GITHUB_LINKS = { \ -e 's%\(PR\|pull request\) *networkupstools/\([^ ][^ ]*\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%link:https://github.com/networkupstools/\2/pull/\3[\1 \2\#\#\3]\4%g' \ -e 's%\([[ ,]\)networkupstools/\([^ ][^ ]*\)\#\([1-9][0-9]*\)\([^0-9]\|$$\)%\1link:https://github.com/networkupstools/\2/issues/\3[\2\#\#\3]\4%g' \ -e 's%\#\(\#[1-9][0-9]*\)%\1%g' \ - > "$@" \ ; } -.adoc.adoc-parsed: - @$(DOCBUILD_FILTER_GITHUB_LINKS) - +DOCBUILD_CONVERT_GITHUB_LINKS = { \ + echo " DOC-ASCIIDOC-GITHUB-LINKS Parsing GitHub link patterns $< => $@"; \ + cat "$<" | $(DOCBUILD_FILTER_GITHUB_LINKS) > "$@.tmp" \ + && mv -f "$@.tmp" "$@" \ +; } +.adoc.adoc-parsed: + @$(DOCBUILD_CONVERT_GITHUB_LINKS) + +../ChangeLog: + @cd $(top_builddir) && $(MAKE) $(AM_FLAGS) ChangeLog + +../ChangeLog.adoc: ../ChangeLog + @echo " DOC-ASCIIDOC $< => $@" \ + && printf "ifdef::txt[]\n== Very detailed Change Log\nendif::txt[]\n\n" > "$@.tmp" \ + && TABCHAR="`printf '\t'`" \ + && $(SED) \ + -e 's,^\([0-9a-zA-Z]\),=== \1,' \ + -e 's,/[+],/\\\\\+,g' \ + -e 's,[+][+],\\\+\\\+,g' \ + -e 's,^\([ '"$${TABCHAR}"'][^+]*\)\([^+/\]\)[+],\1\2\\\+,g' \ + -e 's,^\([ '"$${TABCHAR}"'].*\)\([~|^]\),\1\\\2,g' \ + -e 's,\[\[\([^]]*\)\]\],[\1],g' \ + -e 's,^\(\s\s*\)\([0-9]\),\1{empty}\2,g' \ + < "$<" >> "$@.tmp" \ + && mv -f "$@.tmp" "$@" # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ @@ -189,7 +213,8 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf -release-notes.html release-notes.chunked release-notes.pdf: ../NEWS asciidoc.conf +release-notes.html release-notes.chunked release-notes.pdf: release-notes.txt ../NEWS.adoc-parsed asciidoc.conf +ChangeLog.html ChangeLog.chunked ChangeLog.pdf: ChangeLog.txt ../ChangeLog.adoc-parsed asciidoc.conf solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf # Note: without the "-v", asciidoc (circa 8.6.2) sometimes hangs when @@ -206,6 +231,8 @@ A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \ --attribute=badges \ --attribute=external_title \ --attribute=tree_version="@TREE_VERSION@" \ + --attribute=srcdir="$(abs_srcdir)" \ + --attribute=builddir="$(abs_builddir)" \ -a toc -a numbered --destination-dir=$${A2X_OUTDIR} # NOTE: a2x newer than 8.6.8 says "--destination-dir" is only valid for HTML. # As of version 8.6.9 it lies, and the argument is required for our distcheck diff --git a/docs/documentation.txt b/docs/documentation.txt index 6f5b8035d0..ddc2d1f425 100644 --- a/docs/documentation.txt +++ b/docs/documentation.txt @@ -32,6 +32,8 @@ Developer Documentation ifdef::website[] - NUT Developer Guide (link:docs/developer-guide.chunked/index.html[online]) (link:docs/developer-guide.pdf[PDF]) - NUT Packager Guide (link:docs/packager-guide.chunked/index.html[online]) (link:docs/packager-guide.pdf[PDF]) +- NUT Release Notes (link:docs/release-notes.chunked/index.html[online]) (link:docs/release-notes.pdf[PDF]) +- NUT Change Log (link:docs/ChangeLog.chunked/index.html[online]) (link:docs/ChangeLog.pdf[PDF]) - link:ups-protocols.html[UPS protocols library] - link:docs/man/index.html#Developer_man[Developer manual pages] - link:nut-qa.html[NUT Quality Assurance] @@ -40,6 +42,8 @@ endif::website[] ifndef::website[] - linkdoc:developer-guide[NUT Developer Guide] - linkdoc:packager-guide[NUT Packager Guide] +- linkdoc:release-notes[NUT Release Notes] +- linkdoc:ChangeLog[NUT Change Log] - link:ups-protocols.html[UPS protocols library] - link:../man/index.html#Developer_man[Developer manual pages] - link:nut-qa.html[NUT Quality Assurance] diff --git a/docs/release-notes.txt b/docs/release-notes.txt new file mode 100644 index 0000000000..2ea5ead602 --- /dev/null +++ b/docs/release-notes.txt @@ -0,0 +1,33 @@ +:titles.underlines: "__","==","--","~~","^^" + +Network UPS Tools Release Notes +_______________________________ +:Author: Russell_Kroll,_Arnaud_Quette,_Arjen_de_Korte,_Charles_Lepple_and_Jim_Klimov +:Author Initials: RK, AQ, ADK, CL & JK + +Introduction +============ + +The primary goal of the Network UPS Tools (NUT) project is to provide support +for Power Devices, such as Uninterruptible Power Supplies, Power Distribution +Units and Solar Controllers. + +This document does not intend to detail the change log: it is very large and +complicated to render properly, so is served by another document artifact. + +If you wish to discover how everything came together, have a look at the +<>. + + +[[NUT_Release_Notes]] +NUT Release Notes (and other feature details) +============================================= + +include::{builddir}/../NEWS.adoc-parsed[] + + +[[Project_History]] +Project history +=============== + +include::history.txt[] diff --git a/docs/user-manual.txt b/docs/user-manual.txt index bc66b68148..c106ed1137 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -81,7 +81,7 @@ include::download.txt[] [[_installation_instructions]] -include::../INSTALL.nut.adoc-parsed[] +include::{builddir}/../INSTALL.nut.adoc-parsed[] [[Configuration_notes]] @@ -185,7 +185,7 @@ include::configure.txt[] Appendix I: Upgrading notes =========================== -include::../UPGRADING.adoc-parsed[] +include::{builddir}/../UPGRADING.adoc-parsed[] [[Project_History]] From 1404c35d24b499772b584be888fe263f0e84d616 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 22:20:37 +0200 Subject: [PATCH 0974/1232] docs/Makefile.am: do not refer to generatable "../*.adoc-parsed" files via hardcoded ".." Signed-off-by: Jim Klimov --- docs/Makefile.am | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 44a9cd5f56..2f3c6343fc 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -146,8 +146,8 @@ man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp -CLEANFILES += ../INSTALL.nut ../UPGRADING ../NEWS ../ChangeLog.adoc -CLEANFILES += ../*.adoc-parsed *.adoc-parsed +CLEANFILES += $(top_builddir)/INSTALL.nut $(top_builddir)/UPGRADING $(top_builddir)/NEWS $(top_builddir)/ChangeLog.adoc +CLEANFILES += $(top_builddir)/*.adoc-parsed *.adoc-parsed # Dirs to clean clean-local: @@ -183,10 +183,10 @@ DOCBUILD_CONVERT_GITHUB_LINKS = { \ .adoc.adoc-parsed: @$(DOCBUILD_CONVERT_GITHUB_LINKS) -../ChangeLog: - @cd $(top_builddir) && $(MAKE) $(AM_FLAGS) ChangeLog +$(top_builddir)/ChangeLog: + @cd $(top_builddir) && $(MAKE) $(AM_FLAGS) $(@F) -../ChangeLog.adoc: ../ChangeLog +$(top_builddir)/ChangeLog.adoc: $(top_builddir)/ChangeLog @echo " DOC-ASCIIDOC $< => $@" \ && printf "ifdef::txt[]\n== Very detailed Change Log\nendif::txt[]\n\n" > "$@.tmp" \ && TABCHAR="`printf '\t'`" \ @@ -203,7 +203,7 @@ DOCBUILD_CONVERT_GITHUB_LINKS = { \ # Add other directory deps (not for local EXTRA_DIST) and generated contents FULL_USER_MANUAL_DEPS = $(USER_MANUAL_DEPS) $(SHARED_DEPS) ../README \ - ../INSTALL.nut.adoc-parsed ../UPGRADING.adoc-parsed \ + $(top_builddir)/INSTALL.nut.adoc-parsed $(top_builddir)/UPGRADING.adoc-parsed \ ../TODO.adoc ../scripts/ufw/README.adoc FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ ../scripts/augeas/README.adoc ../TODO.adoc \ @@ -213,8 +213,8 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf -release-notes.html release-notes.chunked release-notes.pdf: release-notes.txt ../NEWS.adoc-parsed asciidoc.conf -ChangeLog.html ChangeLog.chunked ChangeLog.pdf: ChangeLog.txt ../ChangeLog.adoc-parsed asciidoc.conf +release-notes.html release-notes.chunked release-notes.pdf: release-notes.txt $(top_builddir)/NEWS.adoc-parsed asciidoc.conf +ChangeLog.html ChangeLog.chunked ChangeLog.pdf: ChangeLog.txt $(top_builddir)/ChangeLog.adoc-parsed asciidoc.conf solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf # Note: without the "-v", asciidoc (circa 8.6.2) sometimes hangs when From 4afb010859cc0fc1d17c1fd5599774ddb558b60d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 22:28:55 +0200 Subject: [PATCH 0975/1232] NEWS.adoc: change asciidoc link tag Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index bb8fd0c9b7..f1abcca899 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -3,7 +3,7 @@ NUT Release Notes ================= endif::txt[] -If you're upgrading from an earlier version, see the linkdoc:UPGRADING.adoc[] file. +If you're upgrading from an earlier version, see the link:UPGRADING.adoc[] file. For a complete and more detailed list of changes, please refer to the ChangeLog file (generated for release archives), or to the Git version @@ -2543,4 +2543,4 @@ Historic releases More ancient history is not covered in detail here. -You can see linkdoc:docs/history.txt[] for more details. +You can see link:docs/history.txt[] for more details. From 39831946c13977c132812ba323c981b897aac256 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 22:45:35 +0200 Subject: [PATCH 0976/1232] docs/Makefile.am: specify "builddir" path to generated docinfo.xml, and just ship a copy [follow-up from #2046 and probably before] Signed-off-by: Jim Klimov --- docs/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 2f3c6343fc..dcf37b4897 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -51,7 +51,7 @@ ALL_TXT_SRC = nut-names.txt daisychain.txt \ NUT_SPELL_DICT = nut.dict EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ $(CABLES_IMAGES) $(NUT_SPELL_DICT) \ - common.xsl xhtml.xsl chunked.xsl asciidoc.txt + docinfo.xml common.xsl xhtml.xsl chunked.xsl asciidoc.txt ASCIIDOC_HTML_SINGLE = user-manual.html \ developer-guide.html \ @@ -227,6 +227,7 @@ A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \ --xsltproc-opts="--stringparam nut.localdate \"`TZ=UTC date +%Y-%m-%d`\"" \ --xsltproc-opts="--stringparam nut.localtime \"`TZ=UTC date +%H:%M:%S`\"" \ --xsltproc-opts="--stringparam nut.nutversion \"@PACKAGE_VERSION@\"" \ + --attribute=docinfodir="$(builddir)" \ --attribute=iconsdir="$(srcdir)/images" \ --attribute=badges \ --attribute=external_title \ From c007ad5121917150e27aa209aec997a461103a84 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 23:23:21 +0200 Subject: [PATCH 0977/1232] NEWS.adoc: highlight documentation/recipe changes per #1953 Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index f1abcca899..ff83a65772 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -48,6 +48,11 @@ https://github.com/networkupstools/nut/milestone/8 https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=3493 (even though this RFC is not formally an Internet Standard) + - NUT documentation files were rearranged, renaming some to `*.adoc` pattern + to facilitate automatic rendering in GitHub and IDE GUIs, and adding recipe + support for GitHub issue/PR links. This `NEWS` file is now proper asciidoc + rendered into `release-notes.pdf` (and HTML versions) [issue #1953, PR #2048] + - Published a new maintainer GPG key to sign tags and release artifacts, and possibly git commits as well, as part of solution for issue #1410. You can pull it from common OpenPGP servers with the following command: From 0d66a111b02f669e8cb7ba09cdc3564bc17ffdf9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 11 Sep 2023 23:43:37 +0200 Subject: [PATCH 0978/1232] NEWS.adoc: revise asciidoc markup for old-release entries [#1953] Signed-off-by: Jim Klimov --- NEWS.adoc | 532 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 325 insertions(+), 207 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index ff83a65772..6850699a35 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -30,7 +30,7 @@ https://github.com/networkupstools/nut/milestone/10 - (expected) CI automation for coding style - (expected) CI automation for use of data points in drivers that conform - to patterns defined in docs/nut-names.txt + to patterns defined in link:docs/nut-names.txt[] - (expected) Porting of performance and bug fixes from 42ITy project @@ -154,7 +154,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. It is known that at this time some features are not complete, for more details see https://github.com/orgs/networkupstools/projects/2/views/1 * Cross-builds of NUT for Windows using Linux and MinGW (and many custom - built dependency packages, as documented in `scripts/Windows/README`) + built dependency packages, as documented in link:scripts/Windows/README[]) are now regularly tested on NUT CI farm with moderate integration via custom build script `scripts/Windows/build-mingw-nut.sh` [#1489] * Semi-native NUT for Windows builds with MSYS2/MinGW x64 environment are @@ -275,9 +275,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. codebase, and/or prefer non-default system provided implementations (e.g. to use the XPG4 `grep` with `-E` support on Solaris as detailed in https://github.com/networkupstools/nut/issues/1736 comments) - * Build environment configuration notes in `docs/config-prereqs.txt` file - refreshed to cover building of current NUT codebase in CentOS 6 [#1804] - and Solaris 8 [#1736, #1738] + * Build environment configuration notes in link:docs/config-prereqs.txt[] + file refreshed to cover building of current NUT codebase in CentOS 6 + [#1804] and Solaris 8 [#1736, #1738] - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the @@ -286,7 +286,7 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - `configure` script enhanced: `--with-unmapped-data-points` option allows to build SNMP and USB-HID subdrivers with entries discovered by the scripts which generated them from data walks, but developers did not rename yet - to NUT mappings conforming to `docs/nut-names.txt` standards [#1699] + to NUT mappings conforming to link:docs/nut-names.txt[] standards [#1699] - PyNUT.py version bumped to 1.5.0 with some improvements: * `ListClients()` method fixed (was broken in many ways), and is now @@ -941,7 +941,8 @@ Release notes for NUT 2.7.4 - what's new since 2.7.3 - Network protocol information: default to type NUMBER for variables that are not flagged as STRING . This point is subject to improvements or change in - the next release 2.7.5. Refer to docs/net-protocol.txt for more information + the next release 2.7.5. Refer to link:docs/net-protocol.txt[] for more + information - As usual, more bugfixes, cleanup and improvements, on both source code and documentation. @@ -953,7 +954,7 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2 - reverted POWERDOWNFLAG to /etc/killpower as in 2.6.5 (packagers may want to put this in another filesystem, though) - - configure/make fixes for ${systemdsystemunitdir} + - configure/make fixes for `systemdsystemunitdir` - apcsmart: fix command set parsing for protocol version 4 (e.g. Smart-UPS RT 10000 XL) @@ -968,8 +969,9 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2 - USB core: do not call usb_set_altinterface(0) by default - - nutdrv_qx: added fabula, fuji USB and Voltronic-QS-HEX subdrivers; add - bestups subdriver to supersede the old standalone bestups driver + - nutdrv_qx: + * added fabula, fuji USB and Voltronic-QS-HEX subdrivers + * add bestups subdriver to supersede the old standalone bestups driver - NUT Monitor: added FreeDesktop AppData file (including screenshots) @@ -981,9 +983,10 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2 - solis: updated to support APC Microsol units sold in Brazil - - tripplite_usb: updated to use dv/dq charge calculation for all models (also - exposes battery_min and battery max as configuration variables); added - binary 3005 protocol support (such as for SMART500RT1U) + - tripplite_usb: + * updated to use dv/dq charge calculation for all models (also + exposes battery_min and battery max as configuration variables) + * added binary 3005 protocol support (such as for SMART500RT1U) - genericups: better debugging while parsing the cable description flags @@ -995,27 +998,26 @@ Release notes for NUT 2.7.3 - what's new since 2.7.2 XCP USB/serial) * Fix and complete Eaton ePDUs G2/G3 support * ABM (Advanced Battery Monitoring) support through battery.charger.status - in HID (USB and SHUT), XCP (USB and serial) and SNMP (Powerware XUPS - MIB) + in HID (USB and SHUT), XCP (USB and serial) and SNMP (Powerware XUPS MIB) - support for new devices: - APC Back-UPS 1200BR and Back-UPS BZ2200BI-BR (Microsol) - ASEM SPA PB1300 UPS - Belkin Regulator PRO-USB - Cyber Power Systems Value 1500ELCD-RU - EUROCASE EA200N 2000VA - Fideltronik LUPUS 500 - Flight Technic & International (FTUPS) FT-1000BS and FT-1000BS(T) - Grafenthal PR-3000-HS - JAWAN JW-UPSLC02 - Lacerda New Orion 800VA - Mecer ME-1000-WTU - NHS Sistemas de Energia Expert C Online 6000/8000/10000 - NHS Sistemas de Energia Expert S Online 6000/8000/10000 - Powercom BNT-xxxAP (USB product id: 0001) - Rucelf UPOII-3000-96-EL - Tripp Lite OMNIVSINT800 - Voltronic Power Apex 1KVA and Imperial 1KVA + * APC Back-UPS 1200BR and Back-UPS BZ2200BI-BR (Microsol) + * ASEM SPA PB1300 UPS + * Belkin Regulator PRO-USB + * Cyber Power Systems Value 1500ELCD-RU + * EUROCASE EA200N 2000VA + * Fideltronik LUPUS 500 + * Flight Technic & International (FTUPS) FT-1000BS and FT-1000BS(T) + * Grafenthal PR-3000-HS + * JAWAN JW-UPSLC02 + * Lacerda New Orion 800VA + * Mecer ME-1000-WTU + * NHS Sistemas de Energia Expert C Online 6000/8000/10000 + * NHS Sistemas de Energia Expert S Online 6000/8000/10000 + * Powercom BNT-xxxAP (USB product id: 0001) + * Rucelf UPOII-3000-96-EL + * Tripp Lite OMNIVSINT800 + * Voltronic Power Apex 1KVA and Imperial 1KVA Release notes for NUT 2.7.2 - what's new since 2.7.1 @@ -1027,13 +1029,13 @@ Release notes for NUT 2.7.2 - what's new since 2.7.1 This issue was reported on Debian (bug #731156) and is now fixed - support for new devices: - CABAC UPS-1700DV2 - Eaton Powerware 3105 - Emerson Network Power Liebert PSI 1440 - MicroDowell B.Box LP 500 - Numeric Digital 800 plus - OptiUPS VS 575C - Tripp Lite SU10KRT3/1X + * CABAC UPS-1700DV2 + * Eaton Powerware 3105 + * Emerson Network Power Liebert PSI 1440 + * MicroDowell B.Box LP 500 + * Numeric Digital 800 plus + * OptiUPS VS 575C + * Tripp Lite SU10KRT3/1X - FreeDesktop Hardware Abstraction Layer (HAL) support was removed. @@ -1045,7 +1047,7 @@ Release notes for NUT 2.7.2 - what's new since 2.7.1 - snmp-ups: add support for XPPC-MIB and Tripp Lite SU10KRT3/1X. Also fix erroneous status in HP/Compaq SNMP MIB (with the most recent HP - firmware (1.76) ; improved various MIBs (APC, HP/Compaq, ...) + firmware (1.76); improved various MIBs (APC, HP/Compaq, ...) - nutdrv_qx: add new 'fallback' Q1 subdriver, with minimal 'Q1' support. General improvements on all subdrivers. @@ -1073,7 +1075,7 @@ NOTE: There was no public NUT 2.7.0 release. first release after the transition from Subversion to Git. The last release (2.6.5) is almost a year old. A lot of work has been done, but a good amount remains to achieve 2.8.0 goals. - Please read the UPGRADING notes. + Please read the link:UPGRADING.adoc[] notes. - Added support for SSL via the Mozilla NSS library, in addition to the existing OpenSSL support. @@ -1134,8 +1136,8 @@ NOTE: There was no public NUT 2.7.0 release. using Aspell. This includes an interactive build target (make spellcheck-interactive), and an automated one (make spellcheck), mainly for QA / Buildbot purpose. Note that a base NUT dictionary - is also available (docs/nut.dict), providing a glossary of terms - related to power devices and management + is also available (link:docs/nut.dict[]), providing a glossary of + terms related to power devices and management - Improve systemd integration @@ -1153,25 +1155,31 @@ Release notes for NUT 2.6.5 - what's new since 2.6.4 not executed (report and patch from Oliver Schonefeld) - Website hosting: free NUT from Eaton website hosting + + + + NUT website (https://www.networkupstools.org) is no longer hosted by Eaton. Arnaud Quette (NUT project leader) has taken over NUT hosting on his own, to give NUT back some independence. + + + + This effort is also part of a logic to stop crediting Eaton for contributions from others (especially Arnaud Quette, as an individual). The new hosting service is located, as for Arnaud's blog - (http://arnaud.quette.fr) on Gandi servers, using PaaS. This will allow - more flexibility and automation of the release process + (http://arnaud.quette.fr) on Gandi servers, using PaaS. + + + + + This will allow more flexibility and automation of the release process. - macosx-ups: new OS X Power Sources meta-driver - Mac OS X provides UPS status information in a format similar to - what is shown for laptop batteries. This driver will convert that - information into a format compatible with NUT (Charles Lepple). + * Mac OS X provides UPS status information in a format similar to + what is shown for laptop batteries. This driver will convert that + information into a format compatible with NUT (Charles Lepple). - support for new devices: - Eaton ePDU Switched - Online Zinto A (USB ID 0x06da:0x0601) - REDi Blazer 400VA / 600VA / 800VA - UNITEK Alpha650ipF and Alpha650ipE (USB ID 0x0f03:0x0001) + * Eaton ePDU Switched + * Online Zinto A (USB ID 0x06da:0x0601) + * REDi Blazer 400VA / 600VA / 800VA + * UNITEK Alpha650ipF and Alpha650ipE (USB ID 0x0f03:0x0001) - mge-shut driver has been replaced by a new implementation (newmge-shut). In case of issue with this new version, users can revert to oldmge-shut. @@ -1197,22 +1205,29 @@ Release notes for NUT 2.6.5 - what's new since 2.6.4 Release notes for NUT 2.6.4 - what's new since 2.6.3 ---------------------------------------------------- - - This release Fix an important vulnerability in upsd + - This release fixes an important vulnerability in upsd (CVE-2012-2944: upsd can be remotely crashed) - + + + + NUT server (upsd), from versions 2.4.0 to 2.6.3, are exposed to crashes when receiving random data from the network. + + + + This issue is related to the way NUT parses characters, especially from the network. Non printable characters were missed from strings operation (such as strlen), but still copied to the buffer, causing an overflow. + + + + Thus, fix NUT parser, to only allow the subset of ASCII charset from - Space to ~ + `Space` to `~` (Reported by Sebastian Pohle, Alioth bug #313636, CVE-2012-2944) - + + + + A separate patch, which applies to any faulty version, is also available: http://trac.networkupstools.org/projects/nut/changeset/3633 - + + + + For more information, refer to the Common Vulnerabilities and Exposures: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2944 @@ -1234,29 +1249,29 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3 LIST CLIENTS, FSD, HELP and VER (Rene Martín Rodríguez) - support for new devices: - AEG Power Solutions PROTECT HOME - more APC SNMP cards - ATEK Defensor range - all Borri models - all COVER ENERGY SA - CyberPower OR700LCDRM1U, PR6000LCDRTXL5U and CP1000PFCLCD - Dell UPS Network Management Card - Dynamix 1000VA USB - Eaton Management Card Contact (ref 66104) - EVER POWERLINE RT / 11 / 31 and DUO II Pro - GE Digital Energy GT Series 1000-3000 VA - Gtec models - all recent HP serial / USB UPS (G2, G3 and R/T models, ) and HP UPS - Management Module - Ippon INNOVA RT - KOLFF BLACK NOVA - Lexis X-power Tigra 1kVA - Microline C-Lion Innova - Online Yunto YQ450 - PowerShield Defender 1200VA - PowerWalker Online VFI LCD, Line-Interactive VI LCD and Line-Interactive VI - Riello Netman Plus 102 SNMP Card - Tripp-Lite OMNISMART500 + * AEG Power Solutions PROTECT HOME + * more APC SNMP cards + * ATEK Defensor range + * all Borri models + * all COVER ENERGY SA + * CyberPower OR700LCDRM1U, PR6000LCDRTXL5U and CP1000PFCLCD + * Dell UPS Network Management Card + * Dynamix 1000VA USB + * Eaton Management Card Contact (ref 66104) + * EVER POWERLINE RT / 11 / 31 and DUO II Pro + * GE Digital Energy GT Series 1000-3000 VA + * Gtec models + * all recent HP serial / USB UPS (G2, G3 and R/T models, ) and HP UPS + Management Module + * Ippon INNOVA RT + * KOLFF BLACK NOVA + * Lexis X-power Tigra 1kVA + * Microline C-Lion Innova + * Online Yunto YQ450 + * PowerShield Defender 1200VA + * PowerWalker Online VFI LCD, Line-Interactive VI LCD and Line-Interactive VI + * Riello Netman Plus 102 SNMP Card + * Tripp-Lite OMNISMART500 - apcsmart has received some fixes to work better on Mac OS X, and in general @@ -1266,8 +1281,8 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3 - bestfortress has improved Best Fortress LI675VA support - blazer_ser and blazer_usb now try to automatically estimate high and low - voltages, to be able to calculate battery charge ; support for online - Innova UPS (T, RT and 3/1 T) has been added ; Best UPS support has been + voltages, to be able to calculate battery charge; support for online + Innova UPS (T, RT and 3/1 T) has been added; Best UPS support has been improved, to prepare for superseding bestups driver - bestups has also received some care, though users are encouraged to switch @@ -1281,19 +1296,19 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3 including more data and instant commands (Bill Elliot). - usbhid-ups: for Eaton devices, ups.start.auto is now automatically adjusted - for shutdown.{return,stayoff} to behave as expected ; Liebert firmwares with + for shutdown.{return,stayoff} to behave as expected; Liebert firmwares with incorrect exponents have also been addressed. - snmp-ups now provides support for UPS shutdown, based on usbhid-ups mechanisms (composite commands and fallback). Composite commands are also supported now. This means, for example, that if 'shutdown.return' is not - supported, a combination of 'load.off' + 'load.on' may be used ; - Actual validity of instant commands is now tested before commands addition ; - Eaton/MGE MIB has been cleaned and completed ; 3-phases support has been - added to Socomec Netvision MIB ; HP/Compaq MIB has been completed, with + supported, a combination of 'load.off' + 'load.on' may be used; + Actual validity of instant commands is now tested before commands addition; + Eaton/MGE MIB has been cleaned and completed; 3-phases support has been + added to Socomec Netvision MIB; HP/Compaq MIB has been completed, with thresholds, nominal values and more commands. - - nut-scanner now also has libupsclient has a weak runtime dependency ; more + - nut-scanner now also has libupsclient has a weak runtime dependency; more docs and bugfixes have also happened. - Provide an Uncomplicated Firewall (UFW) profile (nut.ufw.profile) @@ -1327,24 +1342,27 @@ Release notes for NUT 2.6.3 - what's new since 2.6.2 distributed. Some documentation is also available in the developer guide and manual pages have been updated and completed. - - support for new devices: Cyber Power Systems with SNMP RMCARD (100, 201, - 202 and 301) ; Dynamix 650VA USB ; LDLC UPS-1200D ; Tecnoware UPS ERA LCD - 0.65 ; Powercom BNT-xxxAP (USB ID 0d9f:0004) ; Various USB devices using - UPSilon 2000 software. + - support for new devices: + * Cyber Power Systems with SNMP RMCARD (100, 201, 202 and 301) + * Dynamix 650VA USB + * LDLC UPS-1200D + * Tecnoware UPS ERA LCD 0.65 + * Powercom BNT-xxxAP (USB ID 0d9f:0004) + * Various USB devices using UPSilon 2000 software - apcsmart has received minor correction. - bcmxcp_usb now handles disconnection issues and reconnection mechanism. - blazer_usb enables again inclusion of buggy USB Device and Vendor IDs in - udev rules file ; language ID support has been added for USB units from + udev rules file; language ID support has been added for USB units from LDLC, Dynamix and other no names. - nut-ipmipsu has also received some improvements. - - snmp-ups has fixed outlets reported current in aphel_genesisII MIB ; - MGE 3 phases handles better low battery condition ; support for Cyber Power - Systems with SNMP RMCARD has been added ; support of the newer Eaton ePDUs + - snmp-ups has fixed outlets reported current in aphel_genesisII MIB; + MGE 3 phases handles better low battery condition; support for Cyber Power + Systems with SNMP RMCARD has been added; support of the newer Eaton ePDUs has been improved. - upsd doesn't anymore fail to start if at least one of the listening @@ -1354,7 +1372,7 @@ Release notes for NUT 2.6.3 - what's new since 2.6.2 - Avahi support is now automatically enabled, upon detection - jNut (NUT Java interface) adds device discovery support, through a - nut-scanner wrapper ; jNutWebAPI, a HTTP/JSON web service interface, has + nut-scanner wrapper; jNutWebAPI, a HTTP/JSON web service interface, has also been added to interact with upsd and nut-scanner. - Base files for HPUX packaging have been added. This is still a work in @@ -1379,13 +1397,18 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1 - NUT now provides a tool, called 'nut-scanner', to discover supported devices, both local and remote. nut-scanner will help to ease the configuration step, and power infrastructure discovery. + + + + This development, sponsored by Eaton, supports the following methods: * USB, * SNMP, * XML/HTTP (from Eaton), * NUT servers, using the classic connect or Avahi / mDNS methods. - + + + + IPMI support will be added in the next release. + + + + A separate library, called 'libnutscan', is also available to provide these feature. Future NUT releases will provides binding for the supported languages (Perl, Python and Java). @@ -1394,14 +1417,21 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1 This development, sponsored by Eaton, is currently limited to the client interface. But it will be broaden to device discovery and configuration in the future. + + + + For more info, refer to nut/scripts/java/README, or the developer guide (chapter 'Creating new client'). Javadoc documentation is also provided, along with Java archives (.jar) in the Download section. - - support for new devices: Eaton 3S ; Cyber Power Systems CP1000AVRLCD ; - various APC models equipped with APC AP9618 management card, including APC - Smart-UPS RT XL ; Orvaldi 750 / 900SP ; POWEREX VI 1000 LED ; PowerWalker - VI 850 LCD ; SVEN Power Pro+ series (USB ID ffff:0000). + - support for new devices: + * Eaton 3S + * Cyber Power Systems CP1000AVRLCD + * various APC models equipped with APC AP9618 management card, including + APC Smart-UPS RT XL + * Orvaldi 750 / 900SP + * POWEREX VI 1000 LED + * PowerWalker VI 850 LCD + * SVEN Power Pro+ series (USB ID ffff:0000) - A regression has been fixed in udev rules file. This previously caused permission issues to owners of some USB devices. @@ -1410,16 +1440,16 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1 service file (nut/scripts/avahi/nut.service). - usbhid-ups has had Eaton completion: some features have been improved, such - as 'output.voltage.nominal' ; 3S Eco control support has been added, along + as 'output.voltage.nominal'; 3S Eco control support has been added, along with battery.runtime.low and end of battery life (life cycle monitoring) - support ; new measurements for 5 PX are also supported now (outlet power + support; new measurements for 5 PX are also supported now (outlet power factor, power, real power and current). - - apcsmart has been updated to support more variables and features ; the + - apcsmart has been updated to support more variables and features; the previous driver is however still available as 'apcsmart-old', in case of issues. - - bcmxcp now supports per outlet startup and shutdown delays setting ; shutdown + - bcmxcp now supports per outlet startup and shutdown delays setting; shutdown delay is also used, when available, for outlet.n.shutdown.return instead of the default 3 seconds. @@ -1451,10 +1481,16 @@ Release notes for NUT 2.6.1 - what's new since 2.6.0 - the Perl module from Gabor Kiss (rewritten from Kit Peters') is now distributed with NUT source code. - - support for new devices: Eaton Ellipse ECO, Powerware 9140, Eaton 5 PX, and - ambient sensor on Eaton ePDU managed ; GE EP series ; Inform Sinus SS 210 ; - IPAR Mini Energy ME 800 ; Mustek Yukai PowerMust 1000 USB ; Numeric 3000 SW ; - SVEN Power Pro+ series (recent models) ; Vivaldi EA200 LED. + - support for new devices: + * Eaton Ellipse ECO, Powerware 9140, Eaton 5 PX, and ambient sensor + on Eaton ePDU managed + * GE EP series + * Inform Sinus SS 210 + * IPAR Mini Energy ME 800 + * Mustek Yukai PowerMust 1000 USB + * Numeric 3000 SW + * SVEN Power Pro+ series (recent models) + * Vivaldi EA200 LED - liebert-esp2: Improved Liebert ESP II support, including UPS shutdown (poweroff), 1 and 3-phase input and output variables, and most @@ -1495,20 +1531,32 @@ NOTE: Per original semantic versioning, there were no public NUT 2.5.x releases. using AsciiDoc. This includes a new website, user manual, developer guide, packager guide and manual pages, available in various formats (single and multiple pages HTML, and PDF at the moment). - Be sure to check the --with-doc configure option help, and - docs/configure.txt for more information. + + + + + Be sure to check the `--with-doc` option help of `configure` script, and + link:docs/configure.txt[] for more information. - Add Augeas support, to provide easy NUT configuration management, through tools and development APIs. For more information, refer to the developer - guide, or scripts/augeas/README in the source directory. + guide, or link:scripts/augeas/README.adoc[] in the source directory. - - support for new devices: APC 5G; Eaton PowerWare 5119 RM (smart mode using - upscode2 driver), Eaton Best Ferrups (using older ConnectUPS card), - Eaton 9395 (serial interface), Eaton ConnectUPS X / BD / E Slot; - HP T1000 INTL, HP T1500 INTL, HP T750 G2, HP R1500 G2 INTL; iDowell iBox UPS; - Tripp Lite SmartOnline SU1000XLA, Tripp Lite Smart1000LCD, and some - more USB/HID devices IDs; CyberPower CP1500AVRLCD and CP1350AVRLCD; - PowerWalker Line-Interactive VI 1400 ; Rocketfish RF-1000VA / RF-1025VA. + - support for new devices: + * APC 5G + * Eaton PowerWare 5119 RM (smart mode using upscode2 driver) + * Eaton Best Ferrups (using older ConnectUPS card) + * Eaton 9395 (serial interface) + * Eaton ConnectUPS X / BD / E Slot + * HP T1000 INTL + * HP T1500 INTL + * HP T750 G2 + * HP R1500 G2 INTL + * iDowell iBox UPS + * Tripp Lite SmartOnline SU1000XLA + * Tripp Lite Smart1000LCD + * and some more USB/HID devices IDs + * CyberPower CP1500AVRLCD and CP1350AVRLCD + * PowerWalker Line-Interactive VI 1400 + * Rocketfish RF-1000VA / RF-1025VA - usbhid-ups has better support for shutting down APC SmartUPS RM series, and finally fix the "buffer size" issue, which was breaking some @@ -1583,16 +1631,23 @@ Release notes for NUT 2.4.2 - what's new since 2.4.1 - the UPower (previously known as DeviceKit-power) rules file is now generated by NUT. - - support for new devices: Apollo 1000A and 1000F; various Baytech RPC; old - Best Power Fortress; Cyber Power Systems PR3000E, CP 1500C and OR2200LCDRM2U; - all the new Dell UPS range (serial, USB and network); Eaton E Series NV and - DX UPS, and Powerware 9130; older HP T500 and T750, newer T750 INTL (USB) and - R1500 G2 (serial); Inform Informer Compact 1000VA; many serial and USB - devices from Ippon, like Back Comfo Pro, Smart Power Pro and Smart Winner; - IVT SCD series; Liebert GXT2-3000RT230 and PowerSure PSA; Mustek PowerMust - 424 / 636 / 848 USB; all new PowerCOM USB devices with HID PDC interface; - Tripp-Lite INTERNETOFFICE700, SMART700USB and ECO550UPS; UPSonic DS-800 - (USB). + - support for new devices: + * Apollo 1000A and 1000F + * various Baytech RPC + * old Best Power Fortress + * Cyber Power Systems PR3000E, CP 1500C and OR2200LCDRM2U + * all the new Dell UPS range (serial, USB and network) + * Eaton E Series NV and DX UPS, and Powerware 9130 + * older HP T500 and T750, newer T750 INTL (USB) and R1500 G2 (serial) + * Inform Informer Compact 1000VA + * many serial and USB devices from Ippon, like Back Comfo Pro, + Smart Power Pro and Smart Winner + * IVT SCD series + * Liebert GXT2-3000RT230 and PowerSure PSA + * Mustek PowerMust 424 / 636 / 848 USB + * all new PowerCOM USB devices with HID PDC interface + * Tripp-Lite INTERNETOFFICE700, SMART700USB and ECO550UPS + * UPSonic DS-800 (USB) Release notes for NUT 2.4.1 - what's new since 2.4.0 @@ -1601,8 +1656,9 @@ Release notes for NUT 2.4.1 - what's new since 2.4.0 - the microdowell driver has appeared to support various MicroDowell Enterprise units (see the "new devices" list below). - - support for new devices: MicroDowell Enterprise B8, B10, N8, N11, N15, N20, - N22, N30, N40, N50, N60 and HiBox ST. + - support for new devices: + * MicroDowell Enterprise B8, B10, N8, N11, N15, N20, + N22, N30, N40, N50, N60 and HiBox ST. - NUT-Monitor now better handles the ups.status field, and has switched to version 1.1. @@ -1617,30 +1673,47 @@ Release notes for NUT 2.4.0 - what's new since 2.2.2 NOTE: Per original semantic versioning, there were no public NUT 2.3.x releases. - - preliminary support for Power Distribution Units (PDUs): NUT now support + - preliminary support for Power Distribution Units (PDUs): NUT can now support PDUs, either natively (ie using NUT snmp-ups driver), or through a binding to the Powerman daemon. The list of supported PDUs is already quite long, - including: Eaton ePDUs (Managed and Monitored), some Aphel models, some - Raritan PDUs, and the whole list of Powerman supported devices: - http://powerman.sourceforge.net/supported.html - - - support for new devices: the various PDUs cited above, Chloride Desk Power - 650, Cyber Power Systems Value 400E/600E/800E (USB models), Delta GES602N, - Digitus DN-170020, the whole Eaton ranges (mostly composed of MGE Office - Protection Systems and Powerware units) including BladeUPS, Forza Power - Technologies SL-1001, HP PowerTrust 2997A, HP R/T 2200 G2, Infosec XP 1000 - and XP 500, Ippon Back Power Pro (serial and USB), Kebo 1200D/D Series, - Liebert PowerSure Personal XT, MGE Office Protection Systems Protection - Station, Neus 400va and 600va, Phasak 400VA and 600VA, Plexus 500VA, Powercom - Black Knight PRO / King PRO and Imperial, PowerKinetics BlackOut Buster, - Sweex 1000 USB, UNITEK Alpha 500, WinPower CPM-800. + including: + * Eaton ePDUs (Managed and Monitored), + * some Aphel models, + * some Raritan PDUs, + * and the whole list of Powerman supported devices: + http://powerman.sourceforge.net/supported.html + + - support for new devices: + * the various PDUs cited above + * Chloride Desk Power 650 + * Cyber Power Systems Value 400E/600E/800E (USB models) + * Delta GES602N + * Digitus DN-170020 + * the whole Eaton ranges (mostly composed of MGE Office Protection Systems + and Powerware units) including BladeUPS + * Forza Power Technologies SL-1001 + * HP PowerTrust 2997A + * HP R/T 2200 G2 + * Infosec XP 1000 and XP 500 + * Ippon Back Power Pro (serial and USB) + * Kebo 1200D/D Series + * Liebert PowerSure Personal XT + * MGE Office Protection Systems Protection Station + * Neus 400va and 600va + * Phasak 400VA and 600VA + * Plexus 500VA + * Powercom Black Knight PRO / King PRO and Imperial + * PowerKinetics BlackOut Buster + * Sweex 1000 USB + * UNITEK Alpha 500 + * WinPower CPM-800 - NUT now embeds Python client support through the PyNUTClient module and the NUT-Monitor application. Both are from David Goncalves, and are still available from http://www.lestat.st. - For more information, refer to scripts/python/README. + For more information, refer to link:scripts/python/README[]. - - the dummy-ups driver now support a "repeater" mode. This allows it to act as + - the dummy-ups driver now supports a "repeater" mode. This allows it to act as a NUT client, and to forward data. This can be useful for supervision and load sharing purposes. @@ -1706,11 +1779,19 @@ Release notes for NUT 2.2.2 - what's new since 2.2.1 Release notes for NUT 2.2.1 - what's new since 2.2.0 ---------------------------------------------------- - - support for new devices: all MGE Office Protection Systems units, - Advice TopGuard 2000, Belkin F6H375-USB, Dynamix UPS1700D, Effekta RM2000MH, - Jageson Technology Jasuny USPS, Powercom SMK-1500A and SXL-1500A, - PowerWalker Line-Interactive VI 400/800 and 600, Powerware 9110, - UNITEK Alpha 2600, UPSonic CXR1000, some vintage serial APC UPSs. + - support for new devices: + * all MGE Office Protection Systems units + * Advice TopGuard 2000 + * Belkin F6H375-USB + * Dynamix UPS1700D + * Effekta RM2000MH, + * Jageson Technology Jasuny USPS + * Powercom SMK-1500A and SXL-1500A + * PowerWalker Line-Interactive VI 400/800 and 600 + * Powerware 9110 + * UNITEK Alpha 2600 + * UPSonic CXR1000 + * some vintage serial APC UPSs - the usbhid-ups driver has been improved, and fixed in many areas, through a backport of the development (trunk) version. @@ -1734,22 +1815,33 @@ NOTE: Per original semantic versioning, there were no public NUT 2.1.x releases. - The new build infrastructure, using automake, is now used. This has major impact on the compilation and installation procedures, and thus on the NUT packaging. - For more information, refer to UPGRADING and packaging/debian/ for + For more information, refer to link:UPGRADING.adoc[] and packaging/debian/ for an example of migration. - NUT now provides support for FreeDesktop Hardware Abstraction Layer (HAL) which brings full Plug And Play experience to USB UPS owners. - For more information, refer to docs/nut-hal.txt. - - - support for new devices: Ablerex 625L, ActivePower 400VA, 2000VA; - Belkin Home Office F6H350-SER, F6H500-SER, F6H650-SER; Belkin Office - Series F6C550-AVR; Belkin Universal UPS F6C100-UNV (USB), F6C1100-UNV - (USB), F6C1200-UNV (USB), F6H350deUNV (serial), F6H350ukUNV (serial), - F6H650ukUNV (serial); Compaq R3000h; Cyber Power Systems PR2200; - Dynex DX-800U; Geek Squad GS1285U; Krauler UP-M500VA; Mecer ME-2000; - MGE UPS SYSTEMS Ellipse MAX; Online Zinto D; PowerTech SMK-800; SVEN - Power Pro+ series, Power Smart RM 2000; Tripp-Lite SmartOnline - SU1500RTXL2ua, smart2200RMXL2U. + For more information, refer to link:docs/nut-hal.txt[]. + + - support for new devices: + * Ablerex 625L + * ActivePower 400VA, 2000VA; + * Belkin Home Office F6H350-SER, F6H500-SER, F6H650-SER + * Belkin Office Series F6C550-AVR + * Belkin Universal UPS F6C100-UNV (USB), F6C1100-UNV (USB), + F6C1200-UNV (USB), F6H350deUNV (serial), + F6H350ukUNV (serial), F6H650ukUNV (serial) + * Compaq R3000h + * Cyber Power Systems PR2200 + * Dynex DX-800U + * Geek Squad GS1285U + * Krauler UP-M500VA + * Mecer ME-2000 + * MGE UPS SYSTEMS Ellipse MAX + * Online Zinto D + * PowerTech SMK-800 + * SVEN Power Pro+ series + * Power Smart RM 2000 + * Tripp-Lite SmartOnline SU1500RTXL2ua, smart2200RMXL2U. - added IPv6 support, @@ -1774,18 +1866,26 @@ NOTE: Per original semantic versioning, there were no public NUT 2.1.x releases. Release notes for NUT 2.0.5 - what's new since 2.0.4 ---------------------------------------------------- - This release is a backport of the development version. Many changes - have already been backported previously. Thus it is more a - synchronization release, though it includes many bugfixes and support - for new models. +This release is a backport of the development version. Many changes +have already been backported previously. Thus it is more a +synchronization release, though it includes many bugfixes and support +for new models. - - support for new devices: APC Smart-UPS with 6TI firmware; Belkin - Small Enterprise F6C1500-TW-RK; Compaq R3000 XR, R5500 XR; Cyber - Power 550SL, 725SL, 685AVR, 800AVR, 1200AVR, AE550; Eltek; Inform - GUARD; Microsol Rhino; Opti-UPS PowerES 420E; PowerMan RealSmart, - BackPro; Powerware PW9315 3-phase; SOLA 305; Tripp-Lite - SMART550USB, SMART2200RMXL2U, OMNI1000LCD, OMNI900LCD, OMNI650LCD, - 1500 LCD, AVR550U; Viewsonic PowerES 420E. + - support for new devices: + * APC Smart-UPS with 6TI firmware + * Belkin Small Enterprise F6C1500-TW-RK + * Compaq R3000 XR, R5500 XR + * Cyber Power 550SL, 725SL, 685AVR, 800AVR, 1200AVR, AE550 + * Eltek + * Inform GUARD + * Microsol Rhino + * Opti-UPS PowerES 420E + * PowerMan RealSmart, BackPro + * Powerware PW9315 3-phase + * SOLA 305 + * Tripp-Lite SMART550USB, SMART2200RMXL2U, OMNI1000LCD, OMNI900LCD, + OMNI650LCD, 1500 LCD, AVR550U + * Viewsonic PowerES 420E - bcmxcp: added 3-phase support @@ -1833,9 +1933,9 @@ Release notes for NUT 2.0.4 - what's new since 2.0.3 [David Kaufman] - The new megatec driver, which will replace a bunch of drivers by nut 2.2 - (refer to docs/megatec.txt and UPGRADING) has been backported from the - trunk (Development tree). The powermust driver has also received some - attention. + (refer to link:docs/megatec.txt[] and link:UPGRADING.adoc[]) has been + backported from the trunk (Development tree). The powermust driver has + also received some attention. [Carlos Rodrigues] - The new rhino driver was added to support Microsol Rhino UPS hardware @@ -2047,9 +2147,8 @@ Release notes for NUT 2.0.1 - what's new since 2.0.0 - The fentonups driver now recognizes several more Megatec protocol units: - - SuperPower HP360, Hope-550 [Denis Zaika] - Unitek Alpha 1000is [Antoine Cuvellard] + * SuperPower HP360, Hope-550 [Denis Zaika] + * Unitek Alpha 1000is [Antoine Cuvellard] - Some variables like uc_sigmask were renamed to avoid clashes with symbols on systems like HP/UX. @@ -2075,14 +2174,16 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x is now mandatory. The 1.4 tree supported both the old (STATUS) and the new (ups.status) as a transitional release, and now that time is over. - + + + + This means that 2.0 is generally smaller than 1.4 code, since the interim compatibility hacks have been removed. - New serial handling code has been added, with greatly simplified operations. The old mess involving repeated calls to sigaction, alarm, and read has been condensed to a select-read loop. - + + + + This change allows drivers which don't do any serial communications at all (hidups, snmp-ups) to drop that baggage, so they are a bit smaller when compiled. @@ -2095,7 +2196,8 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x POWERDOWNFLAG file. If it exists and contains the magic string, then upsmon will exit(EXIT_SUCCESS). Otherwise, it will exit(EXIT_FAILURE). - + + + + This feature can be used to simplify shutdown scripts, since now you don't have to keep the script in sync with the upsmon.conf. @@ -2107,10 +2209,11 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x - The access control system in upsd.conf has been reworked and simplified. Since access levels have become meaningless in recent releases, the new system is just ACCEPT or REJECT . - + + + + If you are upgrading from a previous version of the software, you will have to edit your upsd.conf to use this method. See - the UPGRADING file for more details. + the link:UPGRADING.adoc[] file for more details. - The build process now halts when make fails in one of the subdirectories. @@ -2200,7 +2303,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x of state files, shared memory, or state files with mmap. This change makes many things possible, including the new dynamic variable and command naming scheme described below. - + + + + There is a new development tool called sockdebug in the server directory for debugging driver-server communications on the sockets. @@ -2208,10 +2312,12 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x implementation. Vague names have been turned into meaningful names that fit into an organized system. UTILITY is now input.voltage. OUTVOLT is now output.voltage. - + + + + This also applies to the names of instant commands. BTEST1 is test.battery.start, and BTEST0 is test.battery.stop. - + + + + The old names are still supported for compatibility with older clients. This compatibility mode will be maintained throughout the 1.4 series, and will be gone by the release of 2.0. Users @@ -2225,7 +2331,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x - The drivers and server (upsd) can now change their user ids and chroot themselves with the new -u and -r arguments. This lets you create a "chroot jail" with the bare minimum components. - + + + + This technique is used to provide a higher degree of security. If someone exploited upsd to get a shell somehow, they would be stuck in the jail. @@ -2238,7 +2345,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x - upslog has been reworked to use standard getopt parsing to provide the monitoring settings. The old way of specifying arguments is still supported for backwards compatibility. - + + + + upslog has also been changed to only parse the format string once, rather than doing it every time through the loop. This should provide a minuscule drop in CPU utilization. @@ -2246,8 +2354,9 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x - Usernames are now required in upsmon and upsd. This means that you must add a username to your MONITOR lines in upsmon.conf and then create a matching user in upsd.users. - - Installations from the 1.2 era probably already use usernames, so + + + + + Installations from the 1.2 era probably already used usernames, so this mostly affects those from 1.0 and before. - Drivers are now pinged regularly by upsd when they aren't posting @@ -2260,17 +2369,20 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x - upsstats now reuses connections to upsd when cycling through multiple entries in the hosts.conf. This makes things a bit faster and avoids some of the noise in the syslog. - + + + + This only applies to entries that are adjacent. To take advantage - of this feature, you may have to rearrange them. - + of this feature, you may have to rearrange them per example below. + + + + + Connection reuse for nonadjacent entries may be considered in the + future. +---- MONITOR ups-1@host-1 ... MONITOR ups-1@host-2 ... MONITOR ups-2@host-2 ... MONITOR ups-3@host-3 ... - - Connection reuse for nonadjacent entries may be considered in the - future. +---- - upsd now warns about insecure configuration files at startup. These files (upsd.conf, upsd.users, and the certfile) should @@ -2291,7 +2403,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x --with-group, and the programs no longer setgid() to a hardcoded value. They now setgid() to the primary group of whatever the user value may be. - + + + + This may be compiled in with --with-user as before, and many programs accept -u to override it at runtime. @@ -2333,7 +2446,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x - The mge-utalk driver had trouble establishing communications in some cases due to the RTS line being set. This has been fixed. - + + + + The mge-shut driver has been added to the tree, and has replaced the older mge-ellipse driver. [Arnaud Quette, Philippe Marzouk] @@ -2342,7 +2456,8 @@ Release notes for NUT 1.4.0 - what's new since 1.2.x be added to drivers where the hardware supports it. This can be used to shut down some components earlier than others to prolong your runtime on battery. - + + + + This is supported in the mge-shut driver now, and may show up in others before long. [Arnaud Quette] @@ -2434,7 +2549,8 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1 - The snmp-ups driver has been upgraded and expanded. It now supports multiple MIBs, meaning it can handle RFC 1628, APCC, and MGE equipment. You can pick the right one with "mibs=" in ups.conf. - + + + + Support for setting variable and instant commands is also available. [Arnaud Quette and Dmitry Frolov] @@ -2468,7 +2584,8 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1 shutdown or just annoy users with excessive onbatt/online notify messages. The new code forces the status to settle down for 3 polls before accepting the new value. - + + + + This means that very short power events may not be detected. The alternative is having your machine shut down just because it decided to wiggle over to OB LB for a few seconds. @@ -2482,7 +2599,8 @@ Release notes for NUT 1.2.2 - what's new since 1.2.1 start at the same time. The second upssched would "win", and the first one would be unreachable. This had the side-effect of not being able to cancel timers on the first one. - + + + + If you use upssched, you must define the LOCKFN directive when upgrading to this version, or it will not work. [Gaspar Bakos] From 922345c8189fa2e1496748b177f7e244e4922e7d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Sep 2023 00:00:48 +0200 Subject: [PATCH 0979/1232] docs/release-notes.txt: include UPGRADING as a chapter - it is also release-related info [#1953] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ UPGRADING.adoc | 7 +++++-- docs/Makefile.am | 2 +- docs/release-notes.txt | 15 +++++++++++++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 6850699a35..cadcc9fafd 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -5,6 +5,9 @@ endif::txt[] If you're upgrading from an earlier version, see the link:UPGRADING.adoc[] file. +Please note that web and source document links, product and service names +listed in historic entries of past releases may no longer be relevant. + 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. diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 9a6ec63626..b31dfd9da7 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -7,16 +7,19 @@ This file lists changes that affect users who installed older versions of this software. When upgrading from an older version, be sure to check this file to see if you need to make changes to your system. -NOTE: For packaging (OS distribution or in-house) it is recommended to +[NOTE] +====== +For packaging (OS distribution or in-house) it is recommended to primarily `./configure --with-all` and then excise `--without-something` explicitly for items not supported on your platform, so you do not miss out on new NUT features as they come with new releases. Some may require that you update your build environment with new third-party dependencies, so a broken build of a new NUT release would let you know how to act. -+ + This is a good time to point out that for stricter packaging systems, it may be beneficial to add `--enable-option-checking=fatal` to the `./configure` command line, in order to quickly pick up any other removed option flags. +====== Changes from 2.8.0 to 2.8.1 --------------------------- diff --git a/docs/Makefile.am b/docs/Makefile.am index dcf37b4897..92c87beb58 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -213,7 +213,7 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf -release-notes.html release-notes.chunked release-notes.pdf: release-notes.txt $(top_builddir)/NEWS.adoc-parsed asciidoc.conf +release-notes.html release-notes.chunked release-notes.pdf: release-notes.txt $(top_builddir)/NEWS.adoc-parsed $(top_builddir)/UPGRADING.adoc-parsed asciidoc.conf ChangeLog.html ChangeLog.chunked ChangeLog.pdf: ChangeLog.txt $(top_builddir)/ChangeLog.adoc-parsed asciidoc.conf solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf diff --git a/docs/release-notes.txt b/docs/release-notes.txt index 2ea5ead602..8a53bf83d9 100644 --- a/docs/release-notes.txt +++ b/docs/release-notes.txt @@ -12,8 +12,12 @@ The primary goal of the Network UPS Tools (NUT) project is to provide support for Power Devices, such as Uninterruptible Power Supplies, Power Distribution Units and Solar Controllers. -This document does not intend to detail the change log: it is very large and -complicated to render properly, so is served by another document artifact. +This document intends to report high-level changes delivered by NUT project +releases, as well as practical nuances for packagers and end-users who would +be upgrading their NUT deployments. + +It DOES NOT intend to detail the change log: it is very large and complicated +to render properly, so is better served by another document artifact. If you wish to discover how everything came together, have a look at the <>. @@ -26,6 +30,13 @@ NUT Release Notes (and other feature details) include::{builddir}/../NEWS.adoc-parsed[] +[[NUT_Upgrading_Notes]] +NUT Upgrading Notes +=================== + +include::{builddir}/../UPGRADING.adoc-parsed[] + + [[Project_History]] Project history =============== From 641d86b1489bfdbf7eb7ba4e3ebb69e30a166122 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Sep 2023 00:57:56 +0200 Subject: [PATCH 0980/1232] GitIgnore old NEWS file by name [#1953] Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4e8d64892b..c19b88c34b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ Makefile.in /depcomp /INSTALL /INSTALL.nut +/NEWS /TODO /UPGRADING /install-sh From 445137e862263a48bb1e86f087bd514df2c5f78f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Sep 2023 08:31:23 +0000 Subject: [PATCH 0981/1232] GitIgnore *.adoc*.tmp leftovers, if present [#1953] Probably meaning a broken build, though... Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c19b88c34b..3ee98559d8 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ Makefile.in /test-driver *-spellchecked *.adoc-parsed +*.adoc*.tmp /cppcheck*.xml /.ci*.log /.ci*.log.* From 7e10f8a511e6ce64de5f03b4ddd33e031d46fe80 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Sep 2023 08:32:46 +0000 Subject: [PATCH 0982/1232] docs/Makefile.am: adjust for BSD make implementation Signed-off-by: Jim Klimov --- docs/Makefile.am | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 92c87beb58..03f1902562 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -184,10 +184,24 @@ DOCBUILD_CONVERT_GITHUB_LINKS = { \ @$(DOCBUILD_CONVERT_GITHUB_LINKS) $(top_builddir)/ChangeLog: - @cd $(top_builddir) && $(MAKE) $(AM_FLAGS) $(@F) + @echo " DOC-CHANGELOG-GENERATE $@" \ + && cd $(top_builddir) && $(MAKE) $(AM_FLAGS) $(@F) +# BSD Make dislikes the path resolution here and does not always +# populate "$<", but it has a "$?" for "list of dependencies that +# are newer than the target". For more details see +# https://man.freebsd.org/cgi/man.cgi $(top_builddir)/ChangeLog.adoc: $(top_builddir)/ChangeLog - @echo " DOC-ASCIIDOC $< => $@" \ + @INPUT="$<"; \ + test -n "$${INPUT}" || INPUT="$?" ; \ + test -n "$${INPUT}" && test -n "$@" && test -s "$${INPUT}" \ + || { \ + MSG="FAILED to resolve input or output filename with this make implementation, or input was not generated!"; \ + echo " DOC-CHANGELOG-ASCIIDOC SKIP: $${MSG}" >&2; \ + test -n "$@" && echo "$${MSG}" > "$@" ; \ + exit ; \ + } ; \ + echo " DOC-CHANGELOG-ASCIIDOC $${INPUT} => $@" \ && printf "ifdef::txt[]\n== Very detailed Change Log\nendif::txt[]\n\n" > "$@.tmp" \ && TABCHAR="`printf '\t'`" \ && $(SED) \ @@ -198,7 +212,7 @@ $(top_builddir)/ChangeLog.adoc: $(top_builddir)/ChangeLog -e 's,^\([ '"$${TABCHAR}"'].*\)\([~|^]\),\1\\\2,g' \ -e 's,\[\[\([^]]*\)\]\],[\1],g' \ -e 's,^\(\s\s*\)\([0-9]\),\1{empty}\2,g' \ - < "$<" >> "$@.tmp" \ + < "$${INPUT}" >> "$@.tmp" \ && mv -f "$@.tmp" "$@" # Add other directory deps (not for local EXTRA_DIST) and generated contents From 25c399f0591215d178b3a2c08c267a0dfb3056f7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Sep 2023 20:00:30 +0200 Subject: [PATCH 0983/1232] docs/nut.dict: add (Eaton) IPM 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 dc8e864487..d28fc966c2 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3214 utf-8 +personal_ws-1.1 en 3215 utf-8 AAS ABI ACFAIL @@ -510,6 +510,7 @@ INVOLT IPAR IPBX IPC +IPM IPs IPv IRC From 49c3bb0b367ac561609444f7ad64089124e9ecb8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 10:57:18 +0200 Subject: [PATCH 0984/1232] docs/history.txt: add "Backwards and Forwards Compatibility" chapter evicted from README.adoc Signed-off-by: Jim Klimov --- docs/history.txt | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/history.txt b/docs/history.txt index 633e6b2c71..77159050ff 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -336,6 +336,55 @@ the serial port were dropped from the tree. This tree was released as 2.0.0. +Backwards and Forwards Compatibility (NUT v1.x vs. v2.x) +-------------------------------------------------------- + +The old network code spans a range from about 0.41.1 when TCP support +was introduced up to the recent 1.4 series. It used variable names +like STATUS, UTILITY, and LOADPCT. Many of these names go back to the +earliest prototypes of this software from 1997. At that point there +was no way to know that so many drivers would come along and introduce +so many new variables and commands. The resulting mess grew out of +control over the years. + +During the 1.3 development cycle, all variables and instant commands +were renamed to fit into a tree-like structure. There are major groups, +like input, output and battery. Members of those groups have been +arranged to make sense - input.voltage and output.voltage compliment +each other. The old names were UTILITY and OUTVOLT. The benefits in +this change are obvious. + +The 1.4 clients can talk to either type of server, and can handle either +naming scheme. 1.4 servers have a compatibility mode where they can +answer queries for both names, even though the drivers are internally +using the new format. + +When 1.4 clients talk to 1.4 or 2.0 (or more recent) servers, they will +use the new names. + +Here's a table to make it easier to visualize: + +[options="header"] +|============================================= +| 4+| Server version +| *Client version* | 1.0 | 1.2 | 1.4 | 2.0+ +| 1.0 | yes | yes | yes | no +| 1.2 | yes | yes | yes | no +| 1.4 | yes | yes | yes | yes +| 2.0+ | no | no | yes | yes +|============================================= + +Version 2.0, and more recent, do not contain backwards compatibility for +the old protocol and variable/command names. As a result, 2.0 clients can't +talk to anything older than a 1.4 server. If you ask a 2.0 client to +fetch "STATUS", it will fail. You'll have to ask for "ups.status" +instead. + +Authors of separate monitoring programs should have used the 1.4 series +to write support for the new variables and command names. Client +software can easily support both versions as long as they like. If upsd +returns 'ERR UNKNOWN-COMMAND' to a GET request, you need to use REQ. + networkupstools.org ------------------- From eca1c30b4beeb9fab781722940cbbded0c56965b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 11:04:25 +0200 Subject: [PATCH 0985/1232] Makefile.am: separate EXTRA_DIST for *.adoc and other filename patterns [#1953] Signed-off-by: Jim Klimov --- Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1fd4e564e0..ed0e93b862 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,8 +19,16 @@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status libtool -# COPYING is included automatically. -EXTRA_DIST = INSTALL.nut.adoc LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING.adoc TODO.adoc NEWS.adoc +# COPYING and other autotools-standard files are included automatically +# by automake. Note that the INSTALL file is (re-)imposed by autotools +# runs and is essentially a manual on configure script general usage, so +# NUT's actual installation notes have had to use a different filename. +EXTRA_DIST = LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS + +# Since the renaming of documentation to `*.adoc` extension to help IDE +# and GitHub UIs to render the source files in a pretty fashion, we need +# to list them: +EXTRA_DIST += INSTALL.nut.adoc UPGRADING.adoc TODO.adoc NEWS.adoc # Tarballs created by `make dist` include the `configure.ac` and `m4/*` sources # but lack NUT magic logic to recreate the `configure` script if someone would From 275ce2a9b5999bf12fca0ccacb23d473a5959d37 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:19:17 +0200 Subject: [PATCH 0986/1232] docs: in asciidoc markup (and relevant Makefile rules) require that the trailing slash is part of `(top_)srcdir` and `(top_)builddir` attributes, so empty values are non-toxic Signed-off-by: Jim Klimov --- docs/ChangeLog.txt | 2 +- docs/Makefile.am | 9 +++++++-- docs/man/Makefile.am | 15 +++++++++++---- docs/man/index.txt | 4 ++-- docs/man/nutupsdrv.txt | 4 ++-- docs/man/upsd.txt | 4 ++-- docs/release-notes.txt | 4 ++-- docs/user-manual.txt | 4 ++-- 8 files changed, 29 insertions(+), 17 deletions(-) diff --git a/docs/ChangeLog.txt b/docs/ChangeLog.txt index cb351e3c3d..bd19aeb159 100644 --- a/docs/ChangeLog.txt +++ b/docs/ChangeLog.txt @@ -18,4 +18,4 @@ Very detailed Change Log This document intends to detail the change log for relatively recent work (roughly since the source code was tracked in Git). -include::{builddir}/../ChangeLog.adoc-parsed[] +include::{builddir}../ChangeLog.adoc-parsed[] diff --git a/docs/Makefile.am b/docs/Makefile.am index b9597936fc..563fa8ccc6 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -237,6 +237,9 @@ solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.c # generating the chunked HTML. In this case, export the environment # variable ASCIIDOC_VERBOSE to "-v", ie: # $ ASCIIDOC_VERBOSE=-v make +# Note: `(top_)srcdir` and `(top_)builddir` must end with a path +# separator, or be empty -- so in all cases letting the resulting +# string resolve meaningfully in the filesystem during docs build. A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \ --attribute=icons \ --xsltproc-opts="--nonet" \ @@ -248,8 +251,10 @@ A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \ --attribute=badges \ --attribute=external_title \ --attribute=tree_version="@TREE_VERSION@" \ - --attribute=srcdir="$(abs_srcdir)" \ - --attribute=builddir="$(abs_builddir)" \ + --attribute=srcdir="$(abs_srcdir)/" \ + --attribute=builddir="$(abs_builddir)/" \ + --attribute=top_srcdir="$(abs_top_srcdir)/" \ + --attribute=top_builddir="$(abs_top_builddir)/" \ -a toc -a numbered --destination-dir=$${A2X_OUTDIR} # NOTE: a2x newer than 8.6.8 says "--destination-dir" is only valid for HTML. # As of version 8.6.9 it lies, and the argument is required for our distcheck diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index e5f79bbaf7..65a316beae 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -961,6 +961,9 @@ DOCBUILD_END = { \ ### resolves include paths relative to the main document, so while we ### see the relative builddir as "." in the makefile, for included ### data it would mean the source directory where the .txt resides. +### Note: `(top_)srcdir` and `(top_)builddir` must end with a path +### separator, or be empty -- so in all cases letting the resulting +### string resolve meaningfully in the filesystem during docs build. .txt.html: @A2X_OUTDIR="tmp/man-html.$(@F).$$$$" ; \ echo " DOC-MAN-HTML Generating $@"; \ @@ -969,8 +972,10 @@ DOCBUILD_END = { \ --attribute localdate="`TZ=UTC date +%Y-%m-%d`" \ --attribute localtime="`TZ=UTC date +%H:%M:%S`" \ --attribute nutversion="@PACKAGE_VERSION@" \ - --attribute srcdir="$(abs_srcdir)" \ - --attribute builddir="$(abs_builddir)" \ + --attribute srcdir="$(abs_srcdir)/" \ + --attribute builddir="$(abs_builddir)/" \ + --attribute top_srcdir="$(abs_top_srcdir)/" \ + --attribute top_builddir="$(abs_top_builddir)/" \ -o "$${A2X_OUTDIR}/$(@F)" $< || RES=$$? ; \ $(DOCBUILD_END) ; exit $$RES @@ -981,8 +986,10 @@ A2X_MANPAGE_OPTS = --doctype manpage --format manpage $${A2X_VERBOSE} \ --attribute mansource="Network UPS Tools" \ --attribute manversion="@PACKAGE_VERSION@" \ --attribute manmanual="NUT Manual" \ - --attribute srcdir="$(abs_srcdir)" \ - --attribute builddir="$(abs_builddir)" \ + --attribute srcdir="$(abs_srcdir)/" \ + --attribute builddir="$(abs_builddir)/" \ + --attribute top_srcdir="$(abs_top_srcdir)/" \ + --attribute top_builddir="$(abs_top_builddir)/" \ --destination-dir="$${A2X_OUTDIR}" .txt.1: diff --git a/docs/man/index.txt b/docs/man/index.txt index ad63c3dd4c..9bc37ab8f7 100644 --- a/docs/man/index.txt +++ b/docs/man/index.txt @@ -50,13 +50,13 @@ CGI programs Driver control: ~~~~~~~~~~~~~~~ -include::{builddir}/linkman-drivertool-names.txt[] +include::{builddir}linkman-drivertool-names.txt[] Drivers: ~~~~~~~~ - linkman:nutupsdrv[8] -include::{builddir}/linkman-driver-names.txt[] +include::{builddir}linkman-driver-names.txt[] [[Developer_man]] Developer manual pages diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index 38e64552a9..e1cc17722a 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -262,12 +262,12 @@ CGI programs: Driver control: ~~~~~~~~~~~~~~~ -include::{builddir}/linkman-drivertool-names.txt[] +include::{builddir}linkman-drivertool-names.txt[] Drivers: ~~~~~~~~ -include::{builddir}/linkman-driver-names.txt[] +include::{builddir}linkman-driver-names.txt[] Internet resources: ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/man/upsd.txt b/docs/man/upsd.txt index 28918c3775..d781bb6d7b 100644 --- a/docs/man/upsd.txt +++ b/docs/man/upsd.txt @@ -190,13 +190,13 @@ CGI programs: Driver control: ~~~~~~~~~~~~~~~ -include::{builddir}/linkman-drivertool-names.txt[] +include::{builddir}linkman-drivertool-names.txt[] Drivers: ~~~~~~~~ - linkman:nutupsdrv[8] -include::{builddir}/linkman-driver-names.txt[] +include::{builddir}linkman-driver-names.txt[] Internet resources: ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/release-notes.txt b/docs/release-notes.txt index 8a53bf83d9..c0b989e67e 100644 --- a/docs/release-notes.txt +++ b/docs/release-notes.txt @@ -27,14 +27,14 @@ If you wish to discover how everything came together, have a look at the NUT Release Notes (and other feature details) ============================================= -include::{builddir}/../NEWS.adoc-parsed[] +include::{builddir}../NEWS.adoc-parsed[] [[NUT_Upgrading_Notes]] NUT Upgrading Notes =================== -include::{builddir}/../UPGRADING.adoc-parsed[] +include::{builddir}../UPGRADING.adoc-parsed[] [[Project_History]] diff --git a/docs/user-manual.txt b/docs/user-manual.txt index 3193936e4d..b718b8b668 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -81,7 +81,7 @@ include::download.txt[] [[_installation_instructions]] -include::{builddir}/../INSTALL.nut.adoc-parsed[] +include::{builddir}../INSTALL.nut.adoc-parsed[] [[Configuration_notes]] @@ -185,7 +185,7 @@ include::configure.txt[] Appendix I: Upgrading notes =========================== -include::{builddir}/../UPGRADING.adoc-parsed[] +include::{builddir}../UPGRADING.adoc-parsed[] [[Project_History]] From 78f45419f67d3e5ea42b4a667120bcaaddb0443c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:20:13 +0200 Subject: [PATCH 0987/1232] docs/asciidoc-vars.conf: add an includable asciidoc file with renderer-dependent attribute definitions Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/asciidoc-vars.conf diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf new file mode 100644 index 0000000000..c16b4743b5 --- /dev/null +++ b/docs/asciidoc-vars.conf @@ -0,0 +1,98 @@ +// This file should be included into NUT documentation sources to consistently +// define certain expandable attributes, with contents defined based on the +// rendition target (e.g. GitHub Web UI, plain text, locally built HTML/PDF...) +// +// Since the GitHub UI does not allow use of custom asciidoc configuration +// files, expandable attributes had to be used (usually a set including a +// prefix with meaningful name, and one or more separators and/or a suffix +// with shortened names). For our classic documentation renditions, they +// should resolve to properly defined macros from `docs/asciidoc.conf` +// (usually named same as the variables defined here, for simplicity): +// * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` +// calling the `a2x` tool, since some of the files with the asciidoc +// mark-up are only generated or post-processed during build and +// (due to `make dist` restrictions) being build products, they may +// not reside in same directory as static source text files which +// reference or include them. Note that the non-`top` paths would +// normally differ based on location of the `Makefile` involved +// (e.g. workspace root, or the `docs`, or `docs/man` directories). +// These variables are expected to be absolute paths, or ones relative +// to asciidoc-selected `:base_dir`, and to end with a relevant path +// separator, or be empty -- so in all cases letting the resulting +// string resolve meaningfully in the filesystem during docs build. +// * `linkdoc` allows to refer to a file under `docs/` directory (or +// its nut-website rendition). +// * `xref` substitutes the asciidoc shorthand '<< >>' syntax with +// attributes that conditionally expand to: +// - links on GitHub (references can point at most to a section of +// level docs/common.xsl's ), or +// - xref asciidoc macros when generating docs. +// * `linksingledoc` guarantees that, when chunked HTML is generated, +// the link always points to a non-chunked file. +// * `linkman2` allows to support different names for the manpage and +// the command shown. This is also needed to properly display links +// to manpages in both GitHub and generated docs without defining an +// attribute for each manpage. + +:website-url: https://www.networkupstools.org/ +:srcdir: +:builddir: +:top_srcdir: +:top_builddir: + +// Address links on GitHub vs docs +// (note: 'env-github' attribute is set on GitHub) +// - when generating docs: +ifndef::env-github[] +// * xref -> xref +// syntax: {xref}{x-s}[] +// -> xref:[] +:xref: xref: +:x-s: +// * link to doc -> our macro +// syntax: {linkdoc}{ld-s}[] +// -> linkdoc:[] +:linkdoc: linkdoc: +:ld-s: +// * link to single doc -> our macro +// syntax: {linksingledoc}{lsd-s}[] +// -> linksingledoc:[] +:linksingledoc: linksingledoc: +:lsd-s: +// * link to manpage -> our macro +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// -> linkman2:[,] +:linkman2: linkman2: +:lm-s: [ +:lm-c: , +:lm-e: ] +endif::env-github[] +// - on GitHub: +ifdef::env-github[] +// * xref -> link +// syntax: {xref}{x-s}[] +// In order for it to work, can reference at most a section of +// level docs/common.xsl's +// -> {website-url}docs/user-manual.chunked/.html[] +:xref: {website-url}docs/user-manual.chunked/ +:x-s: .html +// * link to doc -> link +// syntax: {linkdoc}{ld-s}[] +// -> {website-url}docs/.chunked/index.html[] +:linkdoc: {website-url}docs/ +:ld-s: .chunked/index.html +// * link to single doc -> link +// syntax: {linksingledoc}{lsd-s}[] +// -> {website-url}docs/.html[] +:linksingledoc: {website-url}docs/ +:lsd-s: .html +// * link to manpage -> link +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// All the fields are mandatory. +// -> {website-url}docs/man/.html[()] +:linkman2: {website-url}docs/man/ +:lm-s: .html[ +:lm-c: ( +:lm-e: )] +endif::env-github[] + From 38850ba7173a6442e1378a9b9f2a88f7fcbff515 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:22:26 +0200 Subject: [PATCH 0988/1232] README.adoc: move renderer-dependent attribute definitions into includable docs/asciidoc-vars.conf Signed-off-by: Jim Klimov --- README.adoc | 63 +++++------------------------------------------------ 1 file changed, 6 insertions(+), 57 deletions(-) diff --git a/README.adoc b/README.adoc index 954787852c..cb0bd0e33b 100644 --- a/README.adoc +++ b/README.adoc @@ -1,63 +1,12 @@ Network UPS Tools Overview =========================== -:website-url: http://www.networkupstools.org/ - -// Address links on GitHub vs docs -// (note: 'env-github' attribute is set on GitHub) -// - when generating docs: -ifndef::env-github[] -// * xref -> xref -// syntax: {xref}{x-s}[] -// -> xref:[] -:xref: xref: -:x-s: -// * link to doc -> our macro -// syntax: {linkdoc}{ld-s}[] -// -> linkdoc:[] -:linkdoc: linkdoc: -:ld-s: -// * link to single doc -> our macro -// syntax: {linksingledoc}{lsd-s}[] -// -> linksingledoc:[] -:linksingledoc: linksingledoc: -:lsd-s: -// * link to manpage -> our macro -// syntax: {linkman2}{lm-s}{lm-c}{lm-e} -// -> linkman2:[,] -:linkman2: linkman2: -:lm-s: [ -:lm-c: , -:lm-e: ] -endif::env-github[] -// - on GitHub: -ifdef::env-github[] -// * xref -> link -// syntax: {xref}{x-s}[] -// In order for it to work, can reference at most a section of -// level docs/common.xsl's -// -> {website-url}docs/user-manual.chunked/.html[] -:xref: {website-url}docs/user-manual.chunked/ -:x-s: .html -// * link to doc -> link -// syntax: {linkdoc}{ld-s}[] -// -> {website-url}docs/.chunked/index.html[] -:linkdoc: {website-url}docs/ -:ld-s: .chunked/index.html -// * link to single doc -> link -// syntax: {linksingledoc}{lsd-s}[] -// -> {website-url}docs/.html[] -:linksingledoc: {website-url}docs/ -:lsd-s: .html -// * link to manpage -> link -// syntax: {linkman2}{lm-s}{lm-c}{lm-e} -// All the fields are mandatory. -// -> {website-url}docs/man/.html[()] -:linkman2: {website-url}docs/man/ -:lm-s: .html[ -:lm-c: ( -:lm-e: )] -endif::env-github[] +ifndef::top_srcdir[] +include::docs/asciidoc-vars.conf[] +endif::top_srcdir[] +ifdef::top_srcdir[] +include::{top_srcdir}docs/asciidoc-vars.conf[] +endif::top_srcdir[] Description ----------- From 742a92537193bf65a6c8c3bcd1ef4a7d534023fe Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:43:55 +0200 Subject: [PATCH 0989/1232] docs/asciidoc-vars.conf: reshuffle and make it a single block of markup as far as asciidoc is concerned Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index c16b4743b5..e73e947d65 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -8,18 +8,6 @@ // with shortened names). For our classic documentation renditions, they // should resolve to properly defined macros from `docs/asciidoc.conf` // (usually named same as the variables defined here, for simplicity): -// * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` -// calling the `a2x` tool, since some of the files with the asciidoc -// mark-up are only generated or post-processed during build and -// (due to `make dist` restrictions) being build products, they may -// not reside in same directory as static source text files which -// reference or include them. Note that the non-`top` paths would -// normally differ based on location of the `Makefile` involved -// (e.g. workspace root, or the `docs`, or `docs/man` directories). -// These variables are expected to be absolute paths, or ones relative -// to asciidoc-selected `:base_dir`, and to end with a relevant path -// separator, or be empty -- so in all cases letting the resulting -// string resolve meaningfully in the filesystem during docs build. // * `linkdoc` allows to refer to a file under `docs/` directory (or // its nut-website rendition). // * `xref` substitutes the asciidoc shorthand '<< >>' syntax with @@ -33,15 +21,37 @@ // the command shown. This is also needed to properly display links // to manpages in both GitHub and generated docs without defining an // attribute for each manpage. - +// +// Optional attributes set by callers: +// * `website` is used as a boolean toggle in our recipes for nut-website +// vs. offline documentation renditions +// * `env-github` is used as a boolean toggle, set by GitHub WebUI renderer +// * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` +// calling the `a2x` tool, since some of the files with the asciidoc +// mark-up are only generated or post-processed during build and +// (due to `make dist` restrictions) being build products, they may +// not reside in same directory as static source text files which +// reference or include them. Note that the non-`top` paths would +// normally differ based on location of the `Makefile` involved +// (e.g. workspace root, or the `docs`, or `docs/man` directories). +// These variables are expected to be absolute paths, or ones relative +// to asciidoc-selected `:base_dir`, and to end with a relevant path +// separator, or be empty -- so in all cases letting the resulting +// string resolve meaningfully in the filesystem during docs build. +// +// Please keep the remaining comments and definitions as one big block +// so it does not become a series of empty paragraphs in the rendered +// documents! +// :website-url: https://www.networkupstools.org/ :srcdir: :builddir: :top_srcdir: :top_builddir: - +// // Address links on GitHub vs docs // (note: 'env-github' attribute is set on GitHub) +// // - when generating docs: ifndef::env-github[] // * xref -> xref @@ -67,6 +77,7 @@ ifndef::env-github[] :lm-c: , :lm-e: ] endif::env-github[] +// // - on GitHub: ifdef::env-github[] // * xref -> link @@ -95,4 +106,4 @@ ifdef::env-github[] :lm-c: ( :lm-e: )] endif::env-github[] - +// \ No newline at end of file From 6addb3c079e46232839838565c678a7027d93087 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:47:23 +0200 Subject: [PATCH 0990/1232] README.adoc: avoid a blank line between document header and include::docs/asciidoc-vars.conf Signed-off-by: Jim Klimov --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index cb0bd0e33b..cb0b5cbe7a 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ Network UPS Tools Overview =========================== - +// NOTE: No blank line here, document-header include processing should kick in! ifndef::top_srcdir[] include::docs/asciidoc-vars.conf[] endif::top_srcdir[] From a3e9fbe337de33f9f246266299a6d029fc7a92f0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:48:38 +0200 Subject: [PATCH 0991/1232] docs/asciidoc-vars.conf: define our attributes in a different syntactic fashion Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 66 +++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index e73e947d65..e910134be4 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -43,11 +43,27 @@ // so it does not become a series of empty paragraphs in the rendered // documents! // -:website-url: https://www.networkupstools.org/ -:srcdir: -:builddir: -:top_srcdir: -:top_builddir: +// Definitions below use the {set:var:val} syntax to hopefully avoid +// scoping imposed by asciidoc include processing. For more details see +// https://docs.asciidoctor.org/asciidoc/latest/attributes/inline-attribute-entries/ +// +{set:website-url:https://www.networkupstools.org/} +// +ifndef::srcdir[] +{set::srcdir:} +endif::srcdir[] +// +ifndef::builddir[] +{set::builddir:} +endif::builddir[] +// +ifndef::top_srcdir[] +{set::top_srcdir:} +endif::top_srcdir[] +// +ifndef::top_builddir[] +{set::top_builddir:} +endif::top_builddir[] // // Address links on GitHub vs docs // (note: 'env-github' attribute is set on GitHub) @@ -57,25 +73,25 @@ ifndef::env-github[] // * xref -> xref // syntax: {xref}{x-s}[] // -> xref:[] -:xref: xref: -:x-s: +{set:xref:xref:} +{set:x-s:} // * link to doc -> our macro // syntax: {linkdoc}{ld-s}[] // -> linkdoc:[] -:linkdoc: linkdoc: -:ld-s: +{set:linkdoc:linkdoc:} +{set:ld-s:} // * link to single doc -> our macro // syntax: {linksingledoc}{lsd-s}[] // -> linksingledoc:[] -:linksingledoc: linksingledoc: -:lsd-s: +{set:linksingledoc:linksingledoc:} +{set:lsd-s:} // * link to manpage -> our macro // syntax: {linkman2}{lm-s}{lm-c}{lm-e} // -> linkman2:[,] -:linkman2: linkman2: -:lm-s: [ -:lm-c: , -:lm-e: ] +{set:linkman2:linkman2:} +{set:lm-s:[} +{set:lm-c:,} +{set:lm-e:]} endif::env-github[] // // - on GitHub: @@ -85,25 +101,25 @@ ifdef::env-github[] // In order for it to work, can reference at most a section of // level docs/common.xsl's // -> {website-url}docs/user-manual.chunked/.html[] -:xref: {website-url}docs/user-manual.chunked/ -:x-s: .html +{set:xref:{website-url}docs/user-manual.chunked/} +{set:x-s:.html} // * link to doc -> link // syntax: {linkdoc}{ld-s}[] // -> {website-url}docs/.chunked/index.html[] -:linkdoc: {website-url}docs/ -:ld-s: .chunked/index.html +{set:linkdoc:{website-url}docs/} +{set:ld-s:.chunked/index.html} // * link to single doc -> link // syntax: {linksingledoc}{lsd-s}[] // -> {website-url}docs/.html[] -:linksingledoc: {website-url}docs/ -:lsd-s: .html +{set:linksingledoc:{website-url}docs/} +{set:lsd-s:.html} // * link to manpage -> link // syntax: {linkman2}{lm-s}{lm-c}{lm-e} // All the fields are mandatory. // -> {website-url}docs/man/.html[()] -:linkman2: {website-url}docs/man/ -:lm-s: .html[ -:lm-c: ( -:lm-e: )] +{set:linkman2:{website-url}docs/man/} +{set:lm-s:.html[} +{set:lm-c:(} +{set:lm-e:)]} endif::env-github[] // \ No newline at end of file From 618abf7524ed9d8b1c0384fb6acfc860d1de33cd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 12:52:52 +0200 Subject: [PATCH 0992/1232] docs/asciidoc-vars.conf: add a debug NOTE Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index e910134be4..5b9ea718a6 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -92,6 +92,8 @@ ifndef::env-github[] {set:lm-s:[} {set:lm-c:,} {set:lm-e:]} + +NOTE: ASCIIDOC-DEBUG: Included attributes for NUT local/website rendering. endif::env-github[] // // - on GitHub: @@ -121,5 +123,10 @@ ifdef::env-github[] {set:lm-s:.html[} {set:lm-c:(} {set:lm-e:)]} + +NOTE: ASCIIDOC-DEBUG: Included attributes for github rendering. endif::env-github[] -// \ No newline at end of file +// + + +NOTE: ASCIIDOC-DEBUG: Included link:docs/asciidoc-vars.conf[]. From a21b768dbdfc44b3674d9cf2b043710065d3ce68 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 13:00:16 +0200 Subject: [PATCH 0993/1232] README.adoc: refer to top_srcdir first, it WILL be defined after the include Signed-off-by: Jim Klimov --- README.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index cb0b5cbe7a..07e1e6be35 100644 --- a/README.adoc +++ b/README.adoc @@ -1,12 +1,12 @@ Network UPS Tools Overview =========================== // NOTE: No blank line here, document-header include processing should kick in! -ifndef::top_srcdir[] -include::docs/asciidoc-vars.conf[] -endif::top_srcdir[] ifdef::top_srcdir[] include::{top_srcdir}docs/asciidoc-vars.conf[] endif::top_srcdir[] +ifndef::top_srcdir[] +include::docs/asciidoc-vars.conf[] +endif::top_srcdir[] Description ----------- From 5198b041d552fc6e51bfb887d78843c5e8f7fbf2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 13:07:04 +0200 Subject: [PATCH 0994/1232] Revert "docs/asciidoc-vars.conf: add a debug NOTE" This reverts commit 07a39b950b40857c8d8e5c806551e1c40278d3bb. --- docs/asciidoc-vars.conf | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 5b9ea718a6..e910134be4 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -92,8 +92,6 @@ ifndef::env-github[] {set:lm-s:[} {set:lm-c:,} {set:lm-e:]} - -NOTE: ASCIIDOC-DEBUG: Included attributes for NUT local/website rendering. endif::env-github[] // // - on GitHub: @@ -123,10 +121,5 @@ ifdef::env-github[] {set:lm-s:.html[} {set:lm-c:(} {set:lm-e:)]} - -NOTE: ASCIIDOC-DEBUG: Included attributes for github rendering. endif::env-github[] -// - - -NOTE: ASCIIDOC-DEBUG: Included link:docs/asciidoc-vars.conf[]. +// \ No newline at end of file From d17da57b7c3dbd2f30ab34f90add29840aa25c79 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 13:07:05 +0200 Subject: [PATCH 0995/1232] Revert "docs/asciidoc-vars.conf: define our attributes in a different syntactic fashion" This reverts commit 300942904bef0921bba382103c9c4b96cc1c5f04. --- docs/asciidoc-vars.conf | 66 ++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index e910134be4..e73e947d65 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -43,27 +43,11 @@ // so it does not become a series of empty paragraphs in the rendered // documents! // -// Definitions below use the {set:var:val} syntax to hopefully avoid -// scoping imposed by asciidoc include processing. For more details see -// https://docs.asciidoctor.org/asciidoc/latest/attributes/inline-attribute-entries/ -// -{set:website-url:https://www.networkupstools.org/} -// -ifndef::srcdir[] -{set::srcdir:} -endif::srcdir[] -// -ifndef::builddir[] -{set::builddir:} -endif::builddir[] -// -ifndef::top_srcdir[] -{set::top_srcdir:} -endif::top_srcdir[] -// -ifndef::top_builddir[] -{set::top_builddir:} -endif::top_builddir[] +:website-url: https://www.networkupstools.org/ +:srcdir: +:builddir: +:top_srcdir: +:top_builddir: // // Address links on GitHub vs docs // (note: 'env-github' attribute is set on GitHub) @@ -73,25 +57,25 @@ ifndef::env-github[] // * xref -> xref // syntax: {xref}{x-s}[] // -> xref:[] -{set:xref:xref:} -{set:x-s:} +:xref: xref: +:x-s: // * link to doc -> our macro // syntax: {linkdoc}{ld-s}[] // -> linkdoc:[] -{set:linkdoc:linkdoc:} -{set:ld-s:} +:linkdoc: linkdoc: +:ld-s: // * link to single doc -> our macro // syntax: {linksingledoc}{lsd-s}[] // -> linksingledoc:[] -{set:linksingledoc:linksingledoc:} -{set:lsd-s:} +:linksingledoc: linksingledoc: +:lsd-s: // * link to manpage -> our macro // syntax: {linkman2}{lm-s}{lm-c}{lm-e} // -> linkman2:[,] -{set:linkman2:linkman2:} -{set:lm-s:[} -{set:lm-c:,} -{set:lm-e:]} +:linkman2: linkman2: +:lm-s: [ +:lm-c: , +:lm-e: ] endif::env-github[] // // - on GitHub: @@ -101,25 +85,25 @@ ifdef::env-github[] // In order for it to work, can reference at most a section of // level docs/common.xsl's // -> {website-url}docs/user-manual.chunked/.html[] -{set:xref:{website-url}docs/user-manual.chunked/} -{set:x-s:.html} +:xref: {website-url}docs/user-manual.chunked/ +:x-s: .html // * link to doc -> link // syntax: {linkdoc}{ld-s}[] // -> {website-url}docs/.chunked/index.html[] -{set:linkdoc:{website-url}docs/} -{set:ld-s:.chunked/index.html} +:linkdoc: {website-url}docs/ +:ld-s: .chunked/index.html // * link to single doc -> link // syntax: {linksingledoc}{lsd-s}[] // -> {website-url}docs/.html[] -{set:linksingledoc:{website-url}docs/} -{set:lsd-s:.html} +:linksingledoc: {website-url}docs/ +:lsd-s: .html // * link to manpage -> link // syntax: {linkman2}{lm-s}{lm-c}{lm-e} // All the fields are mandatory. // -> {website-url}docs/man/.html[()] -{set:linkman2:{website-url}docs/man/} -{set:lm-s:.html[} -{set:lm-c:(} -{set:lm-e:)]} +:linkman2: {website-url}docs/man/ +:lm-s: .html[ +:lm-c: ( +:lm-e: )] endif::env-github[] // \ No newline at end of file From 9e994368b2f9772774e1377caf4bbfcec5f960bf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:08:57 +0200 Subject: [PATCH 0996/1232] README.adoc: prepare for GH_MARKUP_1095 workarounds Signed-off-by: Jim Klimov --- README.adoc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.adoc b/README.adoc index 07e1e6be35..6920302377 100644 --- a/README.adoc +++ b/README.adoc @@ -1,12 +1,14 @@ Network UPS Tools Overview =========================== // NOTE: No blank line here, document-header include processing should kick in! -ifdef::top_srcdir[] -include::{top_srcdir}docs/asciidoc-vars.conf[] -endif::top_srcdir[] -ifndef::top_srcdir[] -include::docs/asciidoc-vars.conf[] -endif::top_srcdir[] +//GH_MARKUP_1095//ifdef::top_srcdir[] +//GH_MARKUP_1095//include::{top_srcdir}docs/asciidoc-vars.conf[] +//GH_MARKUP_1095//endif::top_srcdir[] +//GH_MARKUP_1095//ifndef::top_srcdir[] +//GH_MARKUP_1095//include::docs/asciidoc-vars.conf[] +//GH_MARKUP_1095//endif::top_srcdir[] +//GH_MARKUP_1095_INCLUDE_BEGIN// +//GH_MARKUP_1095_INCLUDE_END// Description ----------- From a97b70b3f492c4b6753b55a16392ff4596da5107 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:09:14 +0200 Subject: [PATCH 0997/1232] docs/asciidoc-vars.conf: prepare for GH_MARKUP_1095 workarounds Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index e73e947d65..ae4c78b001 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -1,9 +1,17 @@ +// NOTE: The big block of comments and definitions below comes from +// NUT::docs/asciidoc-vars.conf and is included into top-level document +// sources by maintenance recipes directly, due to current limitations +// of the GitHub asciidoc renderer. Hopefully it can be dropped after +// this issue is resolved on their side: +// * https://github.com/github/markup/issues/1095 +// // This file should be included into NUT documentation sources to consistently // define certain expandable attributes, with contents defined based on the // rendition target (e.g. GitHub Web UI, plain text, locally built HTML/PDF...) // // Since the GitHub UI does not allow use of custom asciidoc configuration -// files, expandable attributes had to be used (usually a set including a +// files, or generally does not process the `include:` requests at this time, +// clumsy expandable attributes had to be used (usually a set including a // prefix with meaningful name, and one or more separators and/or a suffix // with shortened names). For our classic documentation renditions, they // should resolve to properly defined macros from `docs/asciidoc.conf` From d14b0c208e2174ab2f0712c89c23c6e5fbf167f0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:10:53 +0200 Subject: [PATCH 0998/1232] Makefile.am: introduce "make maintainer-asciidocs" recipe Signed-off-by: Jim Klimov --- .gitignore | 1 + Makefile.am | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/.gitignore | 1 + 3 files changed, 55 insertions(+) diff --git a/.gitignore b/.gitignore index f9fcfa3a57..9299539f32 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ Makefile.in *-spellchecked *.adoc-parsed *.adoc*.tmp +*.txt*.tmp /cppcheck*.xml /.ci*.log /.ci*.log.* diff --git a/Makefile.am b/Makefile.am index 1a5a3746bb..0e19481847 100644 --- a/Makefile.am +++ b/Makefile.am @@ -149,6 +149,59 @@ man all-man man-man check-man man-html all-html: INSTALL.nut UPGRADING NEWS: cd $(builddir)/docs && $(MAKE) ../$(@F).adoc-parsed && cp -f ../$(@F).adoc-parsed ../$(@F) +# Workarounds for https://github.com/github/markup/issues/1095 +# require direct definition of our attributes in each source +# document, in order for GitHub Web-UI to render them nicely +# (unfortunately, asciidoc configs and includes are not handled +# at this time). Hopefully this will go away at some point. +# The following rule updates definitions in source asciidoc files +# between GH_MARKUP_1095_INCLUDE_BEGIN/END tags with contents of +# current docs/asciidoc-vars.conf file. It is intended to be used +# by maintainers (or brave contributors who would dare edit those +# definitions), to apply them into the committed document sources. +# Not bothering about with "make dist" constraints etc. - changes +# the contents of srcdir directly and intentionally. +maintainer-asciidocs: + @USEDREV="`git log -1 --oneline --pretty=format:'%h (%cs) %s' docs/asciidoc-vars.conf`" || exit ; \ + USEDREV_NOSUBJ="`git log -1 --oneline --pretty=format:'%h (%cs)' docs/asciidoc-vars.conf`" || exit ; \ + echo "$@: Updating asciidoc text sources with docs/asciidoc-vars.conf as of commit: $${USEDREV}"; \ + echo "//GH_MARKUP_1095_INCLUDE_BEGIN//$${USEDREV}" > docs/asciidoc-vars.conf.lastrev.tmp || exit ; \ + find . -name '*.adoc' -or -name '*.txt' | ( \ + FILES=""; \ + while read F ; do \ + grep -E '^//+GH_MARKUP_1095_INCLUDE_(BEGIN|END)' "$$F" >/dev/null \ + || { echo "$@: SKIP: no GH_MARKUP_1095_INCLUDE_* tags: $$F"; continue ; } ; \ + rm -f "$${F}"*.tmp || exit ; \ + EXT="1.tmp"; \ + while IFS='' read LINE ; do \ + case "$${LINE}" in \ + "//GH_MARKUP_1095_INCLUDE_BEGIN"*) EXT="2.tmp" ; continue ;; \ + "//GH_MARKUP_1095_INCLUDE_END"*|"////GH_MARKUP_1095_INCLUDE_END"*) EXT="3.tmp" ; continue ;; \ + esac ; \ + printf '%s\n' "$${LINE}" >> "$${F}.$${EXT}" || exit ; \ + done < "$$F" || { echo "$@: FAILED injection for $${F}" >&2; exit 1; } ; \ + if test -s "$${F}.2.tmp" && test -z "`diff "$${F}.2.tmp" docs/asciidoc-vars.conf | tr -d '\n'`" ; then \ + rm -f "$${F}"*.tmp ; \ + echo "$@: SKIP: no changes: $$F"; continue ; \ + fi; \ + cat "$${F}.1.tmp" docs/asciidoc-vars.conf.lastrev.tmp docs/asciidoc-vars.conf > "$${F}.tmp" \ + && echo '//GH_MARKUP_1095_INCLUDE_END//' >> "$${F}.tmp" \ + && cat "$${F}.3.tmp" >> "$${F}.tmp" \ + && mv -f "$${F}.tmp" "$${F}" \ + || { echo "$@: FAILED injection for $${F}" >&2; exit 1; } ; \ + echo "$@: UPDATED: $$F"; \ + FILES="$${FILES} $${F}"; \ + rm -f "$${F}"*.tmp ; \ + done; \ + rm -f docs/asciidoc-vars.conf.lastrev.tmp; \ + if test -z "$${FILES}" ; then \ + echo "$@: OVERALL-SKIP: No text files found with GH_MARKUP_1095_INCLUDE_ tags, or obsoleted docs/asciidoc-vars.conf contents";\ + else \ + echo "$@: OVERALL-UPDATED: You may now want to:"; \ + echo " git add -p $${FILES} && git commit -sm 'Update NUT documentation sources with current docs/asciidoc-vars.conf: $${USEDREV_NOSUBJ}'"; \ + fi; \ + ) + check-NIT check-NIT-devel: cd $(builddir)/tests/NIT && $(MAKE) $@ diff --git a/docs/.gitignore b/docs/.gitignore index b1abd8207f..c4d2f30a87 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -24,3 +24,4 @@ nut.dict.sorted /*.bak-* /tmp/ docinfo.xml.in.tmp +/asciidoc-vars.conf.lastrev.tmp From f6f990180abd08c19cd1f50465e3bf4e012a94b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:16:02 +0200 Subject: [PATCH 0999/1232] README.adoc: mangle with "make maintainer-asciidocs" Signed-off-by: Jim Klimov --- README.adoc | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 6920302377..32cb62d6e1 100644 --- a/README.adoc +++ b/README.adoc @@ -7,8 +7,124 @@ Network UPS Tools Overview //GH_MARKUP_1095//ifndef::top_srcdir[] //GH_MARKUP_1095//include::docs/asciidoc-vars.conf[] //GH_MARKUP_1095//endif::top_srcdir[] -//GH_MARKUP_1095_INCLUDE_BEGIN// -//GH_MARKUP_1095_INCLUDE_END// +//GH_MARKUP_1095_INCLUDE_BEGIN//146694cff (2023-09-13) docs/asciidoc-vars.conf: prepare for GH_MARKUP_1095 workarounds +// NOTE: The big block of comments and definitions below comes from +// NUT::docs/asciidoc-vars.conf and is included into top-level document +// sources by maintenance recipes directly, due to current limitations +// of the GitHub asciidoc renderer. Hopefully it can be dropped after +// this issue is resolved on their side: +// * https://github.com/github/markup/issues/1095 +// +// This file should be included into NUT documentation sources to consistently +// define certain expandable attributes, with contents defined based on the +// rendition target (e.g. GitHub Web UI, plain text, locally built HTML/PDF...) +// +// Since the GitHub UI does not allow use of custom asciidoc configuration +// files, or generally does not process the `include:` requests at this time, +// clumsy expandable attributes had to be used (usually a set including a +// prefix with meaningful name, and one or more separators and/or a suffix +// with shortened names). For our classic documentation renditions, they +// should resolve to properly defined macros from `docs/asciidoc.conf` +// (usually named same as the variables defined here, for simplicity): +// * `linkdoc` allows to refer to a file under `docs/` directory (or +// its nut-website rendition). +// * `xref` substitutes the asciidoc shorthand '<< >>' syntax with +// attributes that conditionally expand to: +// - links on GitHub (references can point at most to a section of +// level docs/common.xsl's ), or +// - xref asciidoc macros when generating docs. +// * `linksingledoc` guarantees that, when chunked HTML is generated, +// the link always points to a non-chunked file. +// * `linkman2` allows to support different names for the manpage and +// the command shown. This is also needed to properly display links +// to manpages in both GitHub and generated docs without defining an +// attribute for each manpage. +// +// Optional attributes set by callers: +// * `website` is used as a boolean toggle in our recipes for nut-website +// vs. offline documentation renditions +// * `env-github` is used as a boolean toggle, set by GitHub WebUI renderer +// * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` +// calling the `a2x` tool, since some of the files with the asciidoc +// mark-up are only generated or post-processed during build and +// (due to `make dist` restrictions) being build products, they may +// not reside in same directory as static source text files which +// reference or include them. Note that the non-`top` paths would +// normally differ based on location of the `Makefile` involved +// (e.g. workspace root, or the `docs`, or `docs/man` directories). +// These variables are expected to be absolute paths, or ones relative +// to asciidoc-selected `:base_dir`, and to end with a relevant path +// separator, or be empty -- so in all cases letting the resulting +// string resolve meaningfully in the filesystem during docs build. +// +// Please keep the remaining comments and definitions as one big block +// so it does not become a series of empty paragraphs in the rendered +// documents! +// +:website-url: https://www.networkupstools.org/ +:srcdir: +:builddir: +:top_srcdir: +:top_builddir: +// +// Address links on GitHub vs docs +// (note: 'env-github' attribute is set on GitHub) +// +// - when generating docs: +ifndef::env-github[] +// * xref -> xref +// syntax: {xref}{x-s}[] +// -> xref:[] +:xref: xref: +:x-s: +// * link to doc -> our macro +// syntax: {linkdoc}{ld-s}[] +// -> linkdoc:[] +:linkdoc: linkdoc: +:ld-s: +// * link to single doc -> our macro +// syntax: {linksingledoc}{lsd-s}[] +// -> linksingledoc:[] +:linksingledoc: linksingledoc: +:lsd-s: +// * link to manpage -> our macro +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// -> linkman2:[,] +:linkman2: linkman2: +:lm-s: [ +:lm-c: , +:lm-e: ] +endif::env-github[] +// +// - on GitHub: +ifdef::env-github[] +// * xref -> link +// syntax: {xref}{x-s}[] +// In order for it to work, can reference at most a section of +// level docs/common.xsl's +// -> {website-url}docs/user-manual.chunked/.html[] +:xref: {website-url}docs/user-manual.chunked/ +:x-s: .html +// * link to doc -> link +// syntax: {linkdoc}{ld-s}[] +// -> {website-url}docs/.chunked/index.html[] +:linkdoc: {website-url}docs/ +:ld-s: .chunked/index.html +// * link to single doc -> link +// syntax: {linksingledoc}{lsd-s}[] +// -> {website-url}docs/.html[] +:linksingledoc: {website-url}docs/ +:lsd-s: .html +// * link to manpage -> link +// syntax: {linkman2}{lm-s}{lm-c}{lm-e} +// All the fields are mandatory. +// -> {website-url}docs/man/.html[()] +:linkman2: {website-url}docs/man/ +:lm-s: .html[ +:lm-c: ( +:lm-e: )] +endif::env-github[] +////GH_MARKUP_1095_INCLUDE_END// Description ----------- From d459eecb33ec84a73d917b79cdddf51a10d6a854 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:26:31 +0200 Subject: [PATCH 1000/1232] docs/asciidoc-vars.conf: refer to make maintainer-asciidocs Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index ae4c78b001..225f797ef0 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -1,8 +1,8 @@ // NOTE: The big block of comments and definitions below comes from // NUT::docs/asciidoc-vars.conf and is included into top-level document -// sources by maintenance recipes directly, due to current limitations -// of the GitHub asciidoc renderer. Hopefully it can be dropped after -// this issue is resolved on their side: +// sources by maintenance recipes directly (`make maintainer-asciidocs`), +// due to current limitations of the GitHub Web UI asciidoc renderer. +// Hopefully it can be dropped after this issue is resolved on their side: // * https://github.com/github/markup/issues/1095 // // This file should be included into NUT documentation sources to consistently From d2e1b05f5f0c5b04431d8037e12d739ada157938 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:34:15 +0200 Subject: [PATCH 1001/1232] docs/asciidoc-vars.conf: finish the file with newline Signed-off-by: Jim Klimov --- README.adoc | 3 ++- docs/asciidoc-vars.conf | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 32cb62d6e1..f7b1d83307 100644 --- a/README.adoc +++ b/README.adoc @@ -124,7 +124,8 @@ ifdef::env-github[] :lm-c: ( :lm-e: )] endif::env-github[] -////GH_MARKUP_1095_INCLUDE_END// +// +//GH_MARKUP_1095_INCLUDE_END// Description ----------- diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 225f797ef0..962b0753c7 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -114,4 +114,4 @@ ifdef::env-github[] :lm-c: ( :lm-e: )] endif::env-github[] -// \ No newline at end of file +// From 9108a891d44f0b9806c40335b31e86b7e22e635b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:38:31 +0200 Subject: [PATCH 1002/1232] Update NUT documentation sources with current docs/asciidoc-vars.conf: 234b70422 (2023-09-13) Signed-off-by: Jim Klimov --- README.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index f7b1d83307..fd98288275 100644 --- a/README.adoc +++ b/README.adoc @@ -7,12 +7,12 @@ Network UPS Tools Overview //GH_MARKUP_1095//ifndef::top_srcdir[] //GH_MARKUP_1095//include::docs/asciidoc-vars.conf[] //GH_MARKUP_1095//endif::top_srcdir[] -//GH_MARKUP_1095_INCLUDE_BEGIN//146694cff (2023-09-13) docs/asciidoc-vars.conf: prepare for GH_MARKUP_1095 workarounds +//GH_MARKUP_1095_INCLUDE_BEGIN//234b70422 (2023-09-13) docs/asciidoc-vars.conf: finish the file with newline // NOTE: The big block of comments and definitions below comes from // NUT::docs/asciidoc-vars.conf and is included into top-level document -// sources by maintenance recipes directly, due to current limitations -// of the GitHub asciidoc renderer. Hopefully it can be dropped after -// this issue is resolved on their side: +// sources by maintenance recipes directly (`make maintainer-asciidocs`), +// due to current limitations of the GitHub Web UI asciidoc renderer. +// Hopefully it can be dropped after this issue is resolved on their side: // * https://github.com/github/markup/issues/1095 // // This file should be included into NUT documentation sources to consistently From 85bfc7955b00611621c1ba48128fa35459625226 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 15:42:56 +0200 Subject: [PATCH 1003/1232] docs/nut.dict: update for new docs/asciidoc-vars.conf contents Signed-off-by: Jim Klimov --- README.adoc | 2 +- docs/Makefile.am | 3 +++ docs/asciidoc-vars.conf | 2 +- docs/nut.dict | 9 ++++++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index fd98288275..f5ca3ce7d4 100644 --- a/README.adoc +++ b/README.adoc @@ -43,7 +43,7 @@ Network UPS Tools Overview // Optional attributes set by callers: // * `website` is used as a boolean toggle in our recipes for nut-website // vs. offline documentation renditions -// * `env-github` is used as a boolean toggle, set by GitHub WebUI renderer +// * `env-github` is used as a boolean toggle, set by GitHub Web-UI renderer // * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` // calling the `a2x` tool, since some of the files with the asciidoc // mark-up are only generated or post-processed during build and diff --git a/docs/Makefile.am b/docs/Makefile.am index 563fa8ccc6..036a9e05cd 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -354,7 +354,10 @@ if HAVE_ASPELL # its spelling (or errors in that) are not fixable and thus irrelevant. # Similarly for the ../INSTALL file that is prepared by autoconf and not # tracked as a source file by NUT Git repository. +# Note that `docs/asciidoc-vars.conf` is included into docs and so impacts +# their resulting spellcheck verdicts. SPELLCHECK_SRC = $(ALL_TXT_SRC) \ + asciidoc-vars.conf \ ../README.adoc ../NEWS.adoc \ ../INSTALL.nut.adoc ../UPGRADING.adoc \ ../TODO.adoc ../scripts/ufw/README.adoc \ diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 962b0753c7..1eff477413 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -33,7 +33,7 @@ // Optional attributes set by callers: // * `website` is used as a boolean toggle in our recipes for nut-website // vs. offline documentation renditions -// * `env-github` is used as a boolean toggle, set by GitHub WebUI renderer +// * `env-github` is used as a boolean toggle, set by GitHub Web-UI renderer // * `(top_)srcdir` and `(top_)builddir` can be set by `Makefile.am` // calling the `a2x` tool, since some of the files with the asciidoc // mark-up are only generated or post-processed during build and diff --git a/docs/nut.dict b/docs/nut.dict index d28fc966c2..34573c555a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3215 utf-8 +personal_ws-1.1 en 3222 utf-8 AAS ABI ACFAIL @@ -1522,6 +1522,7 @@ armhf asapm ascii asciidoc +asciidocs asciidoctor asem aspell @@ -2253,6 +2254,7 @@ lifecycle linesensitivity linevoltage linkdoc +linksingledoc linux lipo listDeviceClients @@ -2283,6 +2285,7 @@ lowruntime lowvoltsout lposix lr +lsd lsusb lt ltdl @@ -2690,6 +2693,8 @@ regex regtype releasekeyring relicensing +renderer +renderers repo reportId reposurgeon @@ -3079,6 +3084,7 @@ upsuser upswired uptime urb +url urpmi usb usbconfig @@ -3193,6 +3199,7 @@ xpg xr xrealloc xsl +xsl's xsltproc xstrdup xu From 604a0877102543a40da293a2714dd692267d6bbf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 16:06:27 +0200 Subject: [PATCH 1004/1232] configure.ac: revert AM_INIT_AUTOMAKE foreign option (may disable "portability checks" per GNU docs) Signed-off-by: Jim Klimov --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 25f19e3af6..b2619d2c90 100644 --- a/configure.ac +++ b/configure.ac @@ -84,7 +84,7 @@ NUT_CHECK_OS NUT_STASH_WARNINGS AC_CONFIG_HEADERS([include/config.h]) AC_PREFIX_DEFAULT(/usr/local/ups) -AM_INIT_AUTOMAKE([subdir-objects foreign]) +AM_INIT_AUTOMAKE([subdir-objects]) dnl Default to `configure --enable-silent-rules` or `make V=1` for details? dnl This feature seems to require automake-1.13 or newer (1.11+ by other info) From 9ad2279bdc41286ce6f9ba25714ec20bcdeb68b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 16:12:19 +0200 Subject: [PATCH 1005/1232] GitIgnore /.vscode Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9299539f32..1c45b320d6 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,7 @@ __pycache__/ .gdb_history /nbproject /.idea +/.vscode /*.iml # Coredumps From 4af0c95d1d45e7da21ad27586c2788f6aec0eadf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 16:30:00 +0200 Subject: [PATCH 1006/1232] README.adoc: fix xref values for user-manual generation Signed-off-by: Jim Klimov --- README.adoc | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.adoc b/README.adoc index f5ca3ce7d4..8b427c74ad 100644 --- a/README.adoc +++ b/README.adoc @@ -376,13 +376,9 @@ Power distribution unit management NUT also provides an advanced support for power distribution units. You should read the -{xref}Outlets_PDU_notes{x-s}[NUT outlets management and PDU notes] +{xref}outlet_management{x-s}[NUT outlets management and PDU notes] chapter to learn more about when to use this feature. -//////// -<> -//////// - Network Server -------------- @@ -659,7 +655,7 @@ backwards-compatible all the way back to version 1.4. A newer client should fail gracefully when querying an older server. If you need more details about cross-compatibility of older NUT releases -(1.x vs. 2.x), please see the {xref}history{x-s}[Project history] chapter. +(1.x vs. 2.x), please see the {xref}Project_History{x-s}[Project history] chapter. Support / Help / etc. --------------------- From 36f4f0334090c3f289782e9ffac639c27d3ad747 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 16:55:31 +0200 Subject: [PATCH 1007/1232] docs/asciidoc-vars.conf: update maintenance and reasoning comments Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 1eff477413..25e9999b5f 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -2,12 +2,23 @@ // NUT::docs/asciidoc-vars.conf and is included into top-level document // sources by maintenance recipes directly (`make maintainer-asciidocs`), // due to current limitations of the GitHub Web UI asciidoc renderer. -// Hopefully it can be dropped after this issue is resolved on their side: +// Hopefully it can be dropped in favor of compact include definitions +// (see README.adoc for anticipated example) after this issue is resolved +// on their side: // * https://github.com/github/markup/issues/1095 // // This file should be included into NUT documentation sources to consistently // define certain expandable attributes, with contents defined based on the // rendition target (e.g. GitHub Web UI, plain text, locally built HTML/PDF...) +// Note that currently GitHub Web UI references lead to nut-website (as of +// last built and published revision), not to neighboring documents in the +// source browser (which would make sense for branch revisions, etc.) due +// to certain complexity about referencing other-document sections with a +// partially functional rendering engine there. Exploration and fixes are +// welcome (actually working links like +// https://github.com/networkupstools/nut/tree/master#installing or +// https://github.com/networkupstools/nut/blob/master/UPGRADING.adoc#changes-from-274-to-280 +// do seem promising)! // // Since the GitHub UI does not allow use of custom asciidoc configuration // files, or generally does not process the `include:` requests at this time, @@ -31,6 +42,8 @@ // attribute for each manpage. // // Optional attributes set by callers: +// * `website-url` (defaulted below) may be used for "historic website" +// snapshot builds... hopefully // * `website` is used as a boolean toggle in our recipes for nut-website // vs. offline documentation renditions // * `env-github` is used as a boolean toggle, set by GitHub Web-UI renderer From 511b8de9a94748c688db5ad5b59c308b8a49e20d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 16:59:50 +0200 Subject: [PATCH 1008/1232] Update NUT documentation sources with current docs/asciidoc-vars.conf: 36f4f0334 (2023-09-13) Signed-off-by: Jim Klimov --- README.adoc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 8b427c74ad..316ee3b339 100644 --- a/README.adoc +++ b/README.adoc @@ -7,17 +7,28 @@ Network UPS Tools Overview //GH_MARKUP_1095//ifndef::top_srcdir[] //GH_MARKUP_1095//include::docs/asciidoc-vars.conf[] //GH_MARKUP_1095//endif::top_srcdir[] -//GH_MARKUP_1095_INCLUDE_BEGIN//234b70422 (2023-09-13) docs/asciidoc-vars.conf: finish the file with newline +//GH_MARKUP_1095_INCLUDE_BEGIN//36f4f0334 (2023-09-13) docs/asciidoc-vars.conf: update maintenance and reasoning comments // NOTE: The big block of comments and definitions below comes from // NUT::docs/asciidoc-vars.conf and is included into top-level document // sources by maintenance recipes directly (`make maintainer-asciidocs`), // due to current limitations of the GitHub Web UI asciidoc renderer. -// Hopefully it can be dropped after this issue is resolved on their side: +// Hopefully it can be dropped in favor of compact include definitions +// (see README.adoc for anticipated example) after this issue is resolved +// on their side: // * https://github.com/github/markup/issues/1095 // // This file should be included into NUT documentation sources to consistently // define certain expandable attributes, with contents defined based on the // rendition target (e.g. GitHub Web UI, plain text, locally built HTML/PDF...) +// Note that currently GitHub Web UI references lead to nut-website (as of +// last built and published revision), not to neighboring documents in the +// source browser (which would make sense for branch revisions, etc.) due +// to certain complexity about referencing other-document sections with a +// partially functional rendering engine there. Exploration and fixes are +// welcome (actually working links like +// https://github.com/networkupstools/nut/tree/master#installing or +// https://github.com/networkupstools/nut/blob/master/UPGRADING.adoc#changes-from-274-to-280 +// do seem promising)! // // Since the GitHub UI does not allow use of custom asciidoc configuration // files, or generally does not process the `include:` requests at this time, @@ -41,6 +52,8 @@ Network UPS Tools Overview // attribute for each manpage. // // Optional attributes set by callers: +// * `website-url` (defaulted below) may be used for "historic website" +// snapshot builds... hopefully // * `website` is used as a boolean toggle in our recipes for nut-website // vs. offline documentation renditions // * `env-github` is used as a boolean toggle, set by GitHub Web-UI renderer From 65159d7fb0a98e635ef48d592d2f17c7ded1e1e5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 17:55:50 +0200 Subject: [PATCH 1009/1232] docs/asciidoc-vars.conf: fence against duplicate includes Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 25e9999b5f..5728e5fc70 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -1,3 +1,5 @@ +ifndef::asciidoc-vars-nut-included[] +:asciidoc-vars-nut-included: true // NOTE: The big block of comments and definitions below comes from // NUT::docs/asciidoc-vars.conf and is included into top-level document // sources by maintenance recipes directly (`make maintainer-asciidocs`), @@ -127,4 +129,5 @@ ifdef::env-github[] :lm-c: ( :lm-e: )] endif::env-github[] +endif::asciidoc-vars-nut-included[] // From 7c5e90132502d81ca480209581d3377834464963 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 17:58:51 +0200 Subject: [PATCH 1010/1232] docs/asciidoc-vars.conf: fence against re-definitions of website-url and (top_)(src|build)dir attributes Signed-off-by: Jim Klimov --- docs/asciidoc-vars.conf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/asciidoc-vars.conf b/docs/asciidoc-vars.conf index 5728e5fc70..8d8dc89750 100644 --- a/docs/asciidoc-vars.conf +++ b/docs/asciidoc-vars.conf @@ -66,11 +66,26 @@ ifndef::asciidoc-vars-nut-included[] // so it does not become a series of empty paragraphs in the rendered // documents! // +ifndef::website-url[] :website-url: https://www.networkupstools.org/ +endif::website-url[] +// +ifndef::srcdir[] :srcdir: +endif::srcdir[] +// +ifndef::builddir[] :builddir: +endif::builddir[] +// +ifndef::top_srcdir[] :top_srcdir: +endif::top_srcdir[] +// +ifndef::top_builddir[] :top_builddir: +endif::top_builddir[] +// // // Address links on GitHub vs docs // (note: 'env-github' attribute is set on GitHub) From 21bb3975e68e9c1b473cb805c3035dde1e347158 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 17:59:11 +0200 Subject: [PATCH 1011/1232] Update NUT documentation sources with current docs/asciidoc-vars.conf: 7c5e90132 (2023-09-13) Signed-off-by: Jim Klimov --- README.adoc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 316ee3b339..6cf0da879a 100644 --- a/README.adoc +++ b/README.adoc @@ -7,7 +7,9 @@ Network UPS Tools Overview //GH_MARKUP_1095//ifndef::top_srcdir[] //GH_MARKUP_1095//include::docs/asciidoc-vars.conf[] //GH_MARKUP_1095//endif::top_srcdir[] -//GH_MARKUP_1095_INCLUDE_BEGIN//36f4f0334 (2023-09-13) docs/asciidoc-vars.conf: update maintenance and reasoning comments +//GH_MARKUP_1095_INCLUDE_BEGIN//7c5e90132 (2023-09-13) docs/asciidoc-vars.conf: fence against re-definitions of website-url and (top_)(src|build)dir attributes +ifndef::asciidoc-vars-nut-included[] +:asciidoc-vars-nut-included: true // NOTE: The big block of comments and definitions below comes from // NUT::docs/asciidoc-vars.conf and is included into top-level document // sources by maintenance recipes directly (`make maintainer-asciidocs`), @@ -74,11 +76,26 @@ Network UPS Tools Overview // so it does not become a series of empty paragraphs in the rendered // documents! // +ifndef::website-url[] :website-url: https://www.networkupstools.org/ +endif::website-url[] +// +ifndef::srcdir[] :srcdir: +endif::srcdir[] +// +ifndef::builddir[] :builddir: +endif::builddir[] +// +ifndef::top_srcdir[] :top_srcdir: +endif::top_srcdir[] +// +ifndef::top_builddir[] :top_builddir: +endif::top_builddir[] +// // // Address links on GitHub vs docs // (note: 'env-github' attribute is set on GitHub) @@ -137,6 +154,7 @@ ifdef::env-github[] :lm-c: ( :lm-e: )] endif::env-github[] +endif::asciidoc-vars-nut-included[] // //GH_MARKUP_1095_INCLUDE_END// From 4379b90c91e580c05bec04ffa3490a1c3eec6152 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 18:09:00 +0200 Subject: [PATCH 1012/1232] UPGRADING.adoc: highlight changes to documentation source and delivered filenames [#1953] Signed-off-by: Jim Klimov --- UPGRADING.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UPGRADING.adoc b/UPGRADING.adoc index b31dfd9da7..7294e09d81 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -26,6 +26,11 @@ Changes from 2.8.0 to 2.8.1 - PLANNED: Keep track of any further API clean-up? +- NUT documentation recipes were revised, so many of the text source files + were renamed to `*.adoc` pattern. Newly, a `release-notes.pdf` and HTML + equivalents are generated. Packages which deliver documentation may need + to update the lists of files to ship. [#1953] + - Several improvements regarding simultaneous support of USB devices that were previously deemed "identical" and so NUT driver instances did not start for all of them: From d57eef56f86b9068c0be18febcfb7e89d09d5f2d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 22:11:17 +0200 Subject: [PATCH 1013/1232] Makefile.am, docs/Makefile.am: ensure clean-up of (now-)generated README file Signed-off-by: Jim Klimov --- Makefile.am | 2 +- docs/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0e19481847..9c0667c88e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -146,7 +146,7 @@ all-docs check-docs \ man all-man man-man check-man man-html all-html: cd $(builddir)/docs && $(MAKE) $@ -INSTALL.nut UPGRADING NEWS: +INSTALL.nut UPGRADING NEWS README: cd $(builddir)/docs && $(MAKE) ../$(@F).adoc-parsed && cp -f ../$(@F).adoc-parsed ../$(@F) # Workarounds for https://github.com/github/markup/issues/1095 diff --git a/docs/Makefile.am b/docs/Makefile.am index 036a9e05cd..45b2702022 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -146,7 +146,7 @@ man: cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css docinfo.xml.in.tmp -CLEANFILES += $(top_builddir)/INSTALL.nut $(top_builddir)/UPGRADING $(top_builddir)/NEWS $(top_builddir)/ChangeLog.adoc +CLEANFILES += $(top_builddir)/INSTALL.nut $(top_builddir)/UPGRADING $(top_builddir)/NEWS $(top_builddir)/ChangeLog.adoc $(top_builddir)/README CLEANFILES += $(top_builddir)/*.adoc-parsed *.adoc-parsed # Dirs to clean From cca4277befebac3a57691c42d2ecacb59624e093 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 13 Sep 2023 22:24:20 +0200 Subject: [PATCH 1014/1232] Update UPGRADING.adoc Signed-off-by: Jim Klimov --- UPGRADING.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 7294e09d81..ee90a01c8d 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -238,7 +238,7 @@ Changes from 2.7.4 to 2.8.0 with your platform. - dummy-ups can now specify `mode` as a driver argument, and separates the - notion of `dummy-once` (new default for `*.dev` files that do not change) + notion of `dummy-once` (new default for `\*.dev` files that do not change) vs. `dummy-loop` (legacy default for `*.seq` and others) [issue #1385] * Note this can break third-party test scripts which expected `*.dev` @@ -575,7 +575,7 @@ has been gone for a long time, and the target was ambiguous. used newapc, make sure you delete the old binary and fix your ups.conf. Otherwise, you may run the old driver from 1.4. - -*** File trimmed here on changes from 1.2.2 to 1.4.0 *** +File trimmed here on changes from 1.2.2 to 1.4.0 +------------------------------------------------ For information before this point, start with version 2.4.1 and work back. From 1430561f6e28c0d5ff99215429b451ade84a6b83 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 11:44:26 +0200 Subject: [PATCH 1015/1232] docs/developers.txt: update links for SVN to Git migrations Thanks for Tomas Laurinavicius for the suggestion. Signed-off-by: Jim Klimov --- docs/developers.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index 0c3f1244d3..9510288428 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -1427,8 +1427,13 @@ Here is an example workflow: git push username my-new-feature ------------------------------------------------------------------------------ -If you are new to Git, but are familiar with SVN, the -link:http://git-scm.com/course/svn.html[following link] may be of use. +If you are new to Git, but are familiar with SVN, some of the following links +may be of use: + +* link:https://web.archive.org/web/20191224210950/https://git-scm.com/course/svn.html[Git - SVN Crash Course (archived)] +* link:https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git[Git and Other Systems - Migrating to Git] +* link:https://www.git-tower.com/learn/git/ebook/en/command-line/appendix/from-subversion-to-git[Switching from Subversion to Git] +* link:https://www.atlassian.com/git/tutorials/migrating-overview[Migrate from SVN to Git] [[building]] Building the Code From 05610d1564c9ea75d7e10780e2c0f8973e5795ab Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:31:26 +0200 Subject: [PATCH 1016/1232] common/common.c: extend xbasename(), xstrdup() and xrealloc() definition to return NULL if input was NULL (and log it) [#2052] Signed-off-by: Jim Klimov --- common/common.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/common/common.c b/common/common.c index 0864f28b23..3949dbd016 100644 --- a/common/common.c +++ b/common/common.c @@ -643,11 +643,21 @@ int sendsignal(const char *progname, const char * sig) const char *xbasename(const char *file) { + const char *p; +#ifdef WIN32 + const char *r; +#endif + + if (file == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + #ifndef WIN32 - const char *p = strrchr(file, '/'); + p = strrchr(file, '/'); #else - const char *p = strrchr(file, '\\'); - const char *r = strrchr(file, '/'); + p = strrchr(file, '\\'); + r = strrchr(file, '/'); /* if not found, try '/' */ if( r > p ) { p = r; @@ -1729,7 +1739,14 @@ void *xcalloc(size_t number, size_t size) void *xrealloc(void *ptr, size_t size) { - void *p = realloc(ptr, size); + void *p; + + if (ptr == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = realloc(ptr, size); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); @@ -1738,7 +1755,14 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p = strdup(string); + char *p; + + if (string == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From fde7672eff2a2f9b50f5d3353e89e70712f3554f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:39:15 +0200 Subject: [PATCH 1017/1232] clients/upsclient.c: fix strdup()=>xstrdup() to not segfault with bad inputs [#2052] Signed-off-by: Jim Klimov --- clients/upsclient.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clients/upsclient.c b/clients/upsclient.c index 6a823fa57c..f6dea627a5 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1161,7 +1161,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags pconf_init(&ups->pc_ctx, NULL); - ups->host = strdup(host); + ups->host = xstrdup(host); if (!ups->host) { ups->upserror = UPSCLI_ERR_NOMEM; @@ -1618,15 +1618,15 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t s = strchr(tmp, '@'); - if ((*upsname = strdup(strtok_r(tmp, "@", &last))) == NULL) { - fprintf(stderr, "upscli_splitname: strdup failed\n"); + if ((*upsname = xstrdup(strtok_r(tmp, "@", &last))) == NULL) { + fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } /* only a upsname is specified, fill in defaults */ if (s == NULL) { - if ((*hostname = strdup("localhost")) == NULL) { - fprintf(stderr, "upscli_splitname: strdup failed\n"); + if ((*hostname = xstrdup("localhost")) == NULL) { + fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } @@ -1659,8 +1659,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port) return -1; } - if ((*hostname = strdup(strtok_r(tmp+1, "]", &last))) == NULL) { - fprintf(stderr, "upscli_splitaddr: strdup failed\n"); + if ((*hostname = xstrdup(strtok_r(tmp+1, "]", &last))) == NULL) { + fprintf(stderr, "upscli_splitaddr: xstrdup failed\n"); return -1; } @@ -1672,8 +1672,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port) } else { s = strchr(tmp, ':'); - if ((*hostname = strdup(strtok_r(tmp, ":", &last))) == NULL) { - fprintf(stderr, "upscli_splitaddr: strdup failed\n"); + if ((*hostname = xstrdup(strtok_r(tmp, ":", &last))) == NULL) { + fprintf(stderr, "upscli_splitaddr: xstrdup failed\n"); return -1; } From 048876f33f3f405c54b30db6f6ab59c5b6b32872 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:43:08 +0200 Subject: [PATCH 1018/1232] NEWS.adoc: update for issue #2052 fix Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index 171eb2349b..dbef0108fa 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -114,6 +114,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. seems to have confused the MGE SHUT (Serial HID UPS Transfer) driver support [#2022] + - An issue was identified which could cause `libupsclient` parser of device + and host names to crash upon bad inputs (e.g. poorly resolved environment + variables in scripts). Now it should fail more gracefully [#2052] + - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an existing NUT deployment -- for users who are trying if a custom build From d2857f693c8447034818672c171beb59c12e18d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 23:28:04 +0200 Subject: [PATCH 1019/1232] clients/upsclient.c: upscli_splitname(): add explicit checks for empty upsname and/or hostname[:port] parts, to report problems as such [#2052] Signed-off-by: Jim Klimov --- clients/upsclient.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/clients/upsclient.c b/clients/upsclient.c index f6dea627a5..cd30fedf67 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1618,11 +1618,28 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t s = strchr(tmp, '@'); + /* someone passed a "@hostname" string? */ + if (s == tmp) { + fprintf(stderr, "upscli_splitname: got empty upsname string\n"); + return -1; + } + if ((*upsname = xstrdup(strtok_r(tmp, "@", &last))) == NULL) { fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } + /* someone passed a "@hostname" string (take two)? */ + if (!**upsname) { + fprintf(stderr, "upscli_splitname: got empty upsname string\n"); + return -1; + } + + /* + fprintf(stderr, "upscli_splitname3: got buf='%s', tmp='%s', upsname='%s', possible hostname:port='%s'\n", + NUT_STRARG(buf), NUT_STRARG(tmp), NUT_STRARG(*upsname), NUT_STRARG((s ? s+1 : s))); + */ + /* only a upsname is specified, fill in defaults */ if (s == NULL) { if ((*hostname = xstrdup("localhost")) == NULL) { @@ -1634,6 +1651,12 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t return 0; } + /* someone passed a "upsname@" string? */ + if (!(*(s+1))) { + fprintf(stderr, "upscli_splitname: got the @ separator and then an empty hostname[:port] string\n"); + return -1; + } + return upscli_splitaddr(s+1, hostname, port); } From 05edad73910a9b0cd59c732b94c303bfe15ea688 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:18:38 +0200 Subject: [PATCH 1020/1232] Revert "common/common.c: extend xbasename(), xstrdup() and xrealloc() definition to return NULL if input was NULL (and log it) [#2052]" This reverts commit 05610d1564c9ea75d7e10780e2c0f8973e5795ab. Seems to cause segfaults on its own, maybe something relied on older behavior (non-NULLs returned in case of bad inputs?) To investigate separately later... --- common/common.c | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/common/common.c b/common/common.c index 3949dbd016..0864f28b23 100644 --- a/common/common.c +++ b/common/common.c @@ -643,21 +643,11 @@ int sendsignal(const char *progname, const char * sig) const char *xbasename(const char *file) { - const char *p; -#ifdef WIN32 - const char *r; -#endif - - if (file == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - #ifndef WIN32 - p = strrchr(file, '/'); + const char *p = strrchr(file, '/'); #else - p = strrchr(file, '\\'); - r = strrchr(file, '/'); + const char *p = strrchr(file, '\\'); + const char *r = strrchr(file, '/'); /* if not found, try '/' */ if( r > p ) { p = r; @@ -1739,14 +1729,7 @@ void *xcalloc(size_t number, size_t size) void *xrealloc(void *ptr, size_t size) { - void *p; - - if (ptr == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - - p = realloc(ptr, size); + void *p = realloc(ptr, size); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); @@ -1755,14 +1738,7 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p; - - if (string == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - - p = strdup(string); + char *p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From 7c59cf182e0a4eb35ddcc09488180959401838b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:22:06 +0200 Subject: [PATCH 1021/1232] common/common.c: extend xstrdup() definition to return NULL if input was NULL (and log it) [#2052] Signed-off-by: Jim Klimov --- common/common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 0864f28b23..f96584db60 100644 --- a/common/common.c +++ b/common/common.c @@ -1738,7 +1738,14 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p = strdup(string); + char *p; + + if (string == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From d5d5d4dc0dd3781c3983fa76935ae30853f9d15c Mon Sep 17 00:00:00 2001 From: fa Date: Fri, 15 Sep 2023 23:41:03 +0300 Subject: [PATCH 1022/1232] Update blazer_usb.c, libusb0.c, and 7 more files... --- drivers/blazer_usb.c | 8 +++++++- drivers/libusb0.c | 18 ++++++++++++++++++ drivers/libusb1.c | 28 ++++++++++++++++++++++++++++ drivers/nutdrv_qx.c | 11 ++++++++++- drivers/riello_usb.c | 8 +++++++- drivers/tripplite_usb.c | 8 +++++++- drivers/usb-common.c | 28 +++++++++++++++++++++++++--- drivers/usb-common.h | 8 ++++++++ drivers/usbhid-ups.c | 8 +++++++- 9 files changed, 117 insertions(+), 8 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 6cb3337ad7..f7c391a810 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -597,7 +597,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); warn_if_bad_usb_port_filename(device_path); @@ -609,6 +609,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -724,6 +727,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); #endif /* TESTING */ } diff --git a/drivers/libusb0.c b/drivers/libusb0.c index b07a363c0c..62e23ca4f9 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -287,6 +287,9 @@ static int libusb_open(usb_dev_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); /* Keep the list of items in sync with those matched by @@ -298,6 +301,18 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; + upsdebugx(2, "dev->filename: %s", dev->filename); + upsdebugx(2, "bus->dirname: %s", bus->dirname); + +#ifdef WITH_USB_BUSPORT + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + // always zero + sprintf(curDevice->BusPort, "%03d", 0); +#endif + if (dev->descriptor.iManufacturer) { retries = MAX_RETRY; while (retries > 0) { @@ -347,6 +362,9 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); /* FIXME: extend to Eaton OEMs (HP, IBM, ...) */ diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 522d8a183d..95511195ad 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -66,6 +66,9 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); +#ifdef WITH_USB_BUSPORT + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name"); +#endif /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, @@ -163,6 +166,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; uint8_t bus_num, device_addr; +#ifdef WITH_USB_BUSPORT + uint8_t bus_port; +#endif int ret, res; unsigned char buf[20]; const unsigned char *p; @@ -237,6 +243,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); /* Keep the list of items in sync with those matched by @@ -278,6 +287,22 @@ static int nut_libusb_open(libusb_device_handle **udevp, } } +#ifdef WITH_USB_BUSPORT + + bus_port = libusb_get_port_number(device); + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + if (bus_port > 0) { + sprintf(curDevice->BusPort, "%03d", bus_port); + } else { + upsdebugx(1, "%s: invalid libusb bus number %i", + __func__, bus_port); + } +#endif + curDevice->VendorID = dev_desc.idVendor; curDevice->ProductID = dev_desc.idProduct; curDevice->bcdDevice = dev_desc.bcdDevice; @@ -342,6 +367,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown"); upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 83ab443a87..52d29db85f 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3016,6 +3016,9 @@ void upsdrv_initups(void) getval("serial") || getval("bus") || getval("langid_fix") +#ifdef WITH_USB_BUSPORT + || getval("busport") +#endif ) { /* USB */ is_usb = 1; @@ -3110,7 +3113,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); @@ -3121,6 +3124,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* Check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -3284,6 +3290,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); #ifdef QX_SERIAL diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index b0c6a51b5a..93655887d4 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -851,7 +851,7 @@ void upsdrv_initups(void) }; int ret; - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); @@ -864,6 +864,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* pick up the subdriver name if set explicitly */ if (subdrv) { @@ -1232,5 +1235,8 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 84508f8f2e..ff32cb775b 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1568,7 +1568,7 @@ void upsdrv_makevartable(void) */ void upsdrv_initups(void) { - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *value; int r; @@ -1582,6 +1582,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); /* probably won't see this */ regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif r = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); if (r==-1) { @@ -1655,5 +1658,8 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); +#ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +#endif free(curDevice.Device); } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index a45a621168..9500c7dbac 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -119,6 +119,15 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) return 0; } #endif +#ifdef WITH_USB_BUSPORT + #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); + return 0; + } + #endif +#endif #ifdef DEBUG_EXACT_MATCH_DEVICE if (strcmp_null(hd->Device, data->Device) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", @@ -300,7 +309,7 @@ static int match_regex_hex(regex_t *preg, int n) /* private data type: hold a set of compiled regular expressions. */ typedef struct regex_matcher_data_s { - regex_t *regex[7]; + regex_t *regex[8]; } regex_matcher_data_t; /* private callback function for regex matches */ @@ -390,6 +399,19 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) __func__, "Device", hd->Device); return r; } + +#ifdef WITH_USB_BUSPORT + r = match_regex(data->regex[7], hd->BusPort); + if (r != 1) { +/* + upsdebugx(2, "%s: failed match of %s: %s !~ %s", + __func__, "Device", hd->Device, data->regex[6]); +*/ + upsdebugx(2, "%s: failed match of %s: %s", + __func__, "Bus Port", hd->BusPort); + return r; + } +#endif return 1; } @@ -426,7 +448,7 @@ int USBNewRegexMatcher(USBDeviceMatcher_t **matcher, char **regex, int cflags) m->privdata = (void *)data; m->next = NULL; - for (i=0; i<7; i++) { + for (i=0; iregex[i], regex[i], cflags); if (r == -2) { r = i+1; @@ -453,7 +475,7 @@ void USBFreeRegexMatcher(USBDeviceMatcher_t *matcher) data = (regex_matcher_data_t *)matcher->privdata; - for (i = 0; i < 7; i++) { + for (i = 0; i < 8; i++) { if (!data->regex[i]) { continue; } diff --git a/drivers/usb-common.h b/drivers/usb-common.h index a3513adf0d..ae7647f33c 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -460,6 +460,11 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 +#ifdef WITH_USB_BUSPORT +#define REGEXP_ARRAY_LIMIT 8 +#else +#define REGEXP_ARRAY_LIMIT 7 +#endif /*! * USBDevice_t: Describe a USB device. This structure contains exactly @@ -482,6 +487,9 @@ typedef struct USBDevice_s { char *Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ +#ifdef WITH_USB_BUSPORT + char *BusPort; /*!< Port name, e.g. "001" */ +#endif } USBDevice_t; /*! diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 2074970865..c5b16f30c4 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1023,7 +1023,7 @@ void upsdrv_initups(void) subdriver_matcher = device_path; #else /* !SHUT_MODE => USB */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); @@ -1054,6 +1054,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif ret = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); switch(ret) @@ -1176,6 +1179,9 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); +#ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +#endif free(curDevice.Device); #endif /* !SHUT_MODE => USB */ } From ab2032f8f31b601be24cf2cabf4fa17eda3e7b9b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:43:35 +0200 Subject: [PATCH 1023/1232] Rename REGEXP_ARRAY_LIMIT=>USBMATCHER_REGEXP_ARRAY_LIMIT [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 2 +- drivers/nutdrv_qx.c | 2 +- drivers/riello_usb.c | 2 +- drivers/tripplite_usb.c | 2 +- drivers/usb-common.c | 2 +- drivers/usb-common.h | 4 ++-- drivers/usbhid-ups.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index f7c391a810..7dbaef9103 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -597,7 +597,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); warn_if_bad_usb_port_filename(device_path); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 52d29db85f..8925bc1d16 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3113,7 +3113,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 93655887d4..d72fc91492 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -851,7 +851,7 @@ void upsdrv_initups(void) }; int ret; - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index ff32cb775b..3185c8b996 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1568,7 +1568,7 @@ void upsdrv_makevartable(void) */ void upsdrv_initups(void) { - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *value; int r; diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 9500c7dbac..b110d03b16 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -448,7 +448,7 @@ int USBNewRegexMatcher(USBDeviceMatcher_t **matcher, char **regex, int cflags) m->privdata = (void *)data; m->next = NULL; - for (i=0; iregex[i], regex[i], cflags); if (r == -2) { r = i+1; diff --git a/drivers/usb-common.h b/drivers/usb-common.h index ae7647f33c..5f94697b7d 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -461,9 +461,9 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 #ifdef WITH_USB_BUSPORT -#define REGEXP_ARRAY_LIMIT 8 +# define USBMATCHER_REGEXP_ARRAY_LIMIT 8 #else -#define REGEXP_ARRAY_LIMIT 7 +# define USBMATCHER_REGEXP_ARRAY_LIMIT 7 #endif /*! diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index c5b16f30c4..21b6da3c38 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1023,7 +1023,7 @@ void upsdrv_initups(void) subdriver_matcher = device_path; #else /* !SHUT_MODE => USB */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); From 182445251e5a688a0216fcbbdf4727061fb585d0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:45:04 +0200 Subject: [PATCH 1024/1232] Revise "ifdef" indentations Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 10 +++++----- drivers/libusb1.c | 1 - drivers/nutdrv_qx.c | 33 ++++++++++++++++----------------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 7dbaef9103..0563e69012 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -609,9 +609,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +# ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); -#endif +# endif /* check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -727,9 +727,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); -#ifdef WITH_USB_BUSPORT - free(usbdevice.BusPort); -#endif free(usbdevice.Device); +# ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +# endif #endif /* TESTING */ } diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 95511195ad..ad494433ca 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -288,7 +288,6 @@ static int nut_libusb_open(libusb_device_handle **udevp, } #ifdef WITH_USB_BUSPORT - bus_port = libusb_get_port_number(device); curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 8925bc1d16..7366bbe9c6 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3110,7 +3110,7 @@ void upsdrv_initups(void) warn_if_bad_usb_port_filename(device_path); - #ifndef TESTING +# ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; @@ -3124,9 +3124,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +# ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); -#endif +# endif /* Check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -3242,11 +3242,11 @@ void upsdrv_initups(void) } } - #endif /* TESTING */ +# endif /* TESTING */ - #ifdef QX_SERIAL +# ifdef QX_SERIAL } /* is_usb */ - #endif /* QX_SERIAL */ +# endif /* QX_SERIAL */ #endif /* QX_USB */ @@ -3266,23 +3266,22 @@ void upsdrv_cleanup(void) #ifndef TESTING -#ifdef QX_SERIAL +# ifdef QX_SERIAL - #ifdef QX_USB +# ifdef QX_USB if (!is_usb) { - #endif /* QX_USB */ +# endif /* QX_USB */ ser_set_dtr(upsfd, 0); ser_close(upsfd, device_path); - #ifdef QX_USB +# ifdef QX_USB } else { /* is_usb */ - #endif /* QX_USB */ +# endif /* QX_USB */ -#endif /* QX_SERIAL */ - -#ifdef QX_USB +# endif /* QX_SERIAL */ +# ifdef QX_USB usb->close_dev(udev); USBFreeExactMatcher(reopen_matcher); USBFreeRegexMatcher(regex_matcher); @@ -3295,11 +3294,11 @@ void upsdrv_cleanup(void) #endif free(usbdevice.Device); - #ifdef QX_SERIAL +# ifdef QX_SERIAL } /* is_usb */ - #endif /* QX_SERIAL */ +# endif /* QX_SERIAL */ -#endif /* QX_USB */ +# endif /* QX_USB */ #endif /* TESTING */ From 5c3fe5bcd07e9a2547c61c89f80d39bd8a633521 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:45:36 +0200 Subject: [PATCH 1025/1232] drivers/libusb0.c: log a notice that BusPort==0 for libusb0 [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 62e23ca4f9..72ead3b308 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -309,7 +309,7 @@ static int libusb_open(usb_dev_handle **udevp, if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - // always zero + upsdebugx(2, "%s: NOTE: BusPort is always zero with libusb0", __func__); sprintf(curDevice->BusPort, "%03d", 0); #endif From e37d2cf5d169b5a35fb8b355410a30487361ee31 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:46:38 +0200 Subject: [PATCH 1026/1232] drivers/libusb1.c: allow configuring "busport" always, just note it may be ignored in certain builds [#2043] Signed-off-by: Jim Klimov --- drivers/libusb1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index ad494433ca..e1c7096467 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -66,9 +66,11 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); -#ifdef WITH_USB_BUSPORT - addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name"); + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" +#ifndef WITH_USB_BUSPORT + " (tolerated but ignored in this build)" #endif + ); /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, From d8eeaece1f65147c70c7ddb3fde679e2f6b81c7e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:51:57 +0200 Subject: [PATCH 1027/1232] drivers/libusb{0,1}.c: allow configuring "busport" in ups.conf always, just note it may be ignored in certain builds [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 5 +++++ drivers/libusb1.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 72ead3b308..afc76c8db6 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -76,6 +76,11 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); + /* Not supported by libusb0, but let's not crash config + * parsing on unknown keywords due to such nuances! :) */ + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" + " (tolerated but ignored in this build)" + ); /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, diff --git a/drivers/libusb1.c b/drivers/libusb1.c index e1c7096467..90a618eb5d 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -68,6 +68,10 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" #ifndef WITH_USB_BUSPORT + /* Not supported by this version of libusb1, + * but let's not crash config parsing on + * unknown keywords due to such nuances! :) + */ " (tolerated but ignored in this build)" #endif ); From e5b3e971ae3204a716886866543e3710bafa86b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:04:34 +0200 Subject: [PATCH 1028/1232] USB drivers: warn if "busport" is configured but will be ignored by current build [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 4 ++++ drivers/nutdrv_qx.c | 4 ++++ drivers/riello_usb.c | 4 ++++ drivers/usbhid-ups.c | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 0563e69012..187b35d738 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -611,6 +611,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); # ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +# else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } # endif /* check for language ID workaround (#1) */ diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 7366bbe9c6..5c01ac868d 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3126,6 +3126,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); # ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +# else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } # endif /* Check for language ID workaround (#1) */ diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index d72fc91492..32062a089b 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -866,6 +866,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); #ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +#else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } #endif /* pick up the subdriver name if set explicitly */ diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 21b6da3c38..48da548534 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1056,6 +1056,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); #ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +#else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } #endif ret = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); From 92f3e151679dc4fda76c6a0e3764b867da8b3b30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:06:27 +0200 Subject: [PATCH 1029/1232] USB drivers: bump versions due to new "busport" config option support; free the variables in order of definition (ease maintenance) [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 2 +- drivers/libusb0.c | 2 +- drivers/libusb1.c | 2 +- drivers/nutdrv_qx.c | 8 ++++---- drivers/riello_usb.c | 4 ++-- drivers/tripplite_usb.c | 2 +- drivers/usbhid-ups.c | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 187b35d738..53f202a1b7 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -37,7 +37,7 @@ #endif #define DRIVER_NAME "Megatec/Q1 protocol USB driver" -#define DRIVER_VERSION "0.16" +#define DRIVER_VERSION "0.17" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/libusb0.c b/drivers/libusb0.c index afc76c8db6..bc575a6fed 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -37,7 +37,7 @@ #endif #define USB_DRIVER_NAME "USB communication driver (libusb 0.1)" -#define USB_DRIVER_VERSION "0.44" +#define USB_DRIVER_VERSION "0.45" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 90a618eb5d..3e68571d1c 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define USB_DRIVER_NAME "USB communication driver (libusb 1.0)" -#define USB_DRIVER_VERSION "0.45" +#define USB_DRIVER_VERSION "0.46" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 5c01ac868d..f136d9d948 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -57,7 +57,7 @@ #define DRIVER_NAME "Generic Q* Serial driver" #endif /* QX_USB */ -#define DRIVER_VERSION "0.35" +#define DRIVER_VERSION "0.36" #ifdef QX_SERIAL #include "serial.h" @@ -3293,10 +3293,10 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); -#ifdef WITH_USB_BUSPORT - free(usbdevice.BusPort); -#endif free(usbdevice.Device); +# ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +# endif # ifdef QX_SERIAL } /* is_usb */ diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 32062a089b..e85c208e8a 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -34,7 +34,7 @@ #include "riello.h" #define DRIVER_NAME "Riello USB driver" -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "0.10" #define DEFAULT_OFFDELAY 5 /*!< seconds (max 0xFF) */ #define DEFAULT_BOOTDELAY 5 /*!< seconds (max 0xFF) */ @@ -1239,8 +1239,8 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); + free(usbdevice.Device); #ifdef WITH_USB_BUSPORT free(usbdevice.BusPort); #endif - free(usbdevice.Device); } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 3185c8b996..0f767e6fac 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1658,8 +1658,8 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); + free(curDevice.Device); #ifdef WITH_USB_BUSPORT free(curDevice.BusPort); #endif - free(curDevice.Device); } diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 48da548534..d83f989e3c 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -28,7 +28,7 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.50" +#define DRIVER_VERSION "0.51" #define HU_VAR_WAITBEFORERECONNECT "waitbeforereconnect" @@ -1183,10 +1183,10 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); -#ifdef WITH_USB_BUSPORT - free(curDevice.BusPort); -#endif free(curDevice.Device); +# ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +# endif #endif /* !SHUT_MODE => USB */ } From a388e125a828d7d02c93f85c706f1c4df9f22556 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:08:14 +0200 Subject: [PATCH 1030/1232] drivers/usb-common.c: constrain regex_matcher_data_t array size to USBMATCHER_REGEXP_ARRAY_LIMIT too (not a hardcoded number like before) [#2043] Signed-off-by: Jim Klimov --- drivers/usb-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb-common.c b/drivers/usb-common.c index b110d03b16..7e5a307945 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -309,7 +309,7 @@ static int match_regex_hex(regex_t *preg, int n) /* private data type: hold a set of compiled regular expressions. */ typedef struct regex_matcher_data_s { - regex_t *regex[8]; + regex_t *regex[USBMATCHER_REGEXP_ARRAY_LIMIT]; } regex_matcher_data_t; /* private callback function for regex matches */ @@ -475,7 +475,7 @@ void USBFreeRegexMatcher(USBDeviceMatcher_t *matcher) data = (regex_matcher_data_t *)matcher->privdata; - for (i = 0; i < 8; i++) { + for (i = 0; i < USBMATCHER_REGEXP_ARRAY_LIMIT; i++) { if (!data->regex[i]) { continue; } From f79a362da86944d9bfab053e1c14a0cca312bacf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:19:15 +0200 Subject: [PATCH 1031/1232] drivers/libshut.c: update with formal support of "busport" (no-op for serial mode) [#2043] Signed-off-by: Jim Klimov --- drivers/libshut.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/libshut.c b/drivers/libshut.c index 79acd0ade8..ffc1614bc8 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -468,12 +468,24 @@ static int libshut_open( free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); curDevice->VendorID = dev_descriptor->idVendor; curDevice->ProductID = dev_descriptor->idProduct; curDevice->Bus = strdup("serial"); curDevice->Device = strdup(arg_device_path); +#ifdef WITH_USB_BUSPORT + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + upsdebugx(2, "%s: NOTE: BusPort is always zero with libshut", __func__); + sprintf(curDevice->BusPort, "%03d", 0); +#endif + curDevice->bcdDevice = dev_descriptor->bcdDevice; curDevice->Vendor = strdup("Eaton"); if (dev_descriptor->iManufacturer) { @@ -514,6 +526,9 @@ static int libshut_open( upsdebugx(2, "- Product: %s", curDevice->Product); upsdebugx(2, "- Serial Number: %s", curDevice->Serial); upsdebugx(2, "- Bus: %s", curDevice->Bus); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); upsdebugx(2, "Device matches"); From 705e6c72f74e635c85580799a23aac957a673309 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:19:31 +0200 Subject: [PATCH 1032/1232] drivers/libshut.c: avoid potential small memory leak Signed-off-by: Jim Klimov --- drivers/libshut.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/libshut.c b/drivers/libshut.c index ffc1614bc8..ae48dc67ba 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -43,7 +43,7 @@ #include "common.h" /* for xmalloc, upsdebugx prototypes */ #define SHUT_DRIVER_NAME "SHUT communication driver" -#define SHUT_DRIVER_VERSION "0.87" +#define SHUT_DRIVER_VERSION "0.88" /* communication driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -487,7 +487,7 @@ static int libshut_open( #endif curDevice->bcdDevice = dev_descriptor->bcdDevice; - curDevice->Vendor = strdup("Eaton"); + curDevice->Vendor = NULL; if (dev_descriptor->iManufacturer) { ret = shut_get_string_simple(*arg_upsfd, dev_descriptor->iManufacturer, string, MAX_STRING_SIZE); @@ -495,6 +495,9 @@ static int libshut_open( curDevice->Vendor = strdup(string); } } + if (curDevice->Vendor == NULL) { + curDevice->Vendor = strdup("Eaton"); + } /* ensure iProduct retrieval */ if (dev_descriptor->iProduct) { From 72f918cd51ca22b2bd6b9345d14ad81073d6be94 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:21:06 +0200 Subject: [PATCH 1033/1232] drivers/libusb0.c: use logging for bus port consistent with other USB-related libs [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index bc575a6fed..8318301fe1 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -306,9 +306,6 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; - upsdebugx(2, "dev->filename: %s", dev->filename); - upsdebugx(2, "bus->dirname: %s", bus->dirname); - #ifdef WITH_USB_BUSPORT curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { @@ -368,7 +365,7 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); #ifdef WITH_USB_BUSPORT - upsdebugx(2, "- Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); From dbc15b3340c287016ef762bd539b4191b92f8ea2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:25:25 +0200 Subject: [PATCH 1034/1232] NEWS.adoc: document the addition of "busport" config option [#2043] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++++ docs/nut.dict | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index 171eb2349b..7e0265c776 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -233,6 +233,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. of all USB drivers using these options to include the same description [#1766] + - Added a "busport" USB matching option (if supported by the hardware, OS and + libusb on the particular deployment, it should allow to specify physical + port numbers on an USB hub, rather than logical "device" enumeration values, + and in turn -- this should be less volatile across reboots etc.) [#2043] + - Added an `allow_duplicates` flag for common USB matching options which may help monitor several related no-name devices (although without knowing reliably which one is which... better than nothing) [#1756] diff --git a/docs/nut.dict b/docs/nut.dict index 34573c555a..d25aae15a6 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3222 utf-8 +personal_ws-1.1 en 3223 utf-8 AAS ABI ACFAIL @@ -1639,6 +1639,7 @@ bugfixes buildbots builddir bullseye +busport busybox bv bypassvolts From 73e8923ca77a2d5642540975b2f035aeb72bf138 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:34:25 +0200 Subject: [PATCH 1035/1232] docs/man/nut_usb_addvars.txt: fix typo about Linux path to usb device info Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index c9a9c5d1d9..7908aedd47 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -56,15 +56,15 @@ Examples: Select a UPS on a specific USB bus or group of buses. The argument is a regular expression that must match the bus name where the UPS is -connected (e.g. `bus="002"` or `bus="00[2-3]"`) as seen in -`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. +connected (e.g. `bus="002"` or `bus="00[2-3]"`) as seen on Linux in +`/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. *device =* 'regex':: Select a UPS on a specific USB device or group of devices. The argument is a regular expression that must match the device name where the UPS is -connected (e.g. `device="001"` or `device="00[1-2]"`) as seen in -`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. +connected (e.g. `device="001"` or `device="00[1-2]"`) as seen on Linux +in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. From 1eef3173812b54ddd05c689db42c75a8fa9e4f9e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:34:43 +0200 Subject: [PATCH 1036/1232] docs/man/nut_usb_addvars.txt: add "busport" info [#2043] Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 7908aedd47..74a8886ae3 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -68,6 +68,17 @@ in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. +*busport =* 'regex':: + +If supported by the hardware, OS and libusb on the particular deployment, +this option should allow to specify physical port numbers on an USB hub, +rather than logical `device` enumeration values, and in turn -- this should +be less volatile across reboots or re-plugging. ++ +NOTE: this option is not practically supported by some NUT builds +(it should be ignored with a warning then), and not by all systems +that NUT can run on. + *allow_duplicates*:: If you have several UPS devices which may not be uniquely identified by From 844f91a37c2a878ce2ce6f530846cbb080cf43f3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:36:50 +0200 Subject: [PATCH 1037/1232] docs/man/nut_usb_addvars.txt: fix markup for a NOTE about "device" value Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 74a8886ae3..b96b252d8d 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -65,7 +65,8 @@ Select a UPS on a specific USB device or group of devices. The argument is a regular expression that must match the device name where the UPS is connected (e.g. `device="001"` or `device="00[1-2]"`) as seen on Linux in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. -Note that device numbers are not guaranteed by the OS to be stable across ++ +NOTE: device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. *busport =* 'regex':: From 5db58c9ec45e49f2921a6aba096416bf68de6d49 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:47:21 +0200 Subject: [PATCH 1038/1232] m4/nut_check_libusb.m4: detect if we can support "busport" USB matching value [#2043] Signed-off-by: Jim Klimov --- m4/nut_check_libusb.m4 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/m4/nut_check_libusb.m4 b/m4/nut_check_libusb.m4 index 98b0ad0c59..5b042b0790 100644 --- a/m4/nut_check_libusb.m4 +++ b/m4/nut_check_libusb.m4 @@ -286,6 +286,7 @@ if test -z "${nut_have_libusb_seen}"; then nut_have_libusb=no fi + nut_with_usb_busport=no AS_IF([test "${nut_have_libusb}" = "yes"], [ dnl ---------------------------------------------------------------------- dnl additional USB-related checks @@ -318,12 +319,27 @@ if test -z "${nut_have_libusb_seen}"; then ] ) + dnl AC_MSG_CHECKING([for libusb bus port support]) + dnl Per https://github.com/networkupstools/nut/issues/2043#issuecomment-1721856494 : + dnl #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) + dnl DEFINE WITH_USB_BUSPORT + dnl #endif + AC_CHECK_FUNCS(libusb_get_port_number, [nut_with_usb_busport=yes]) + dnl # With USB we can match desired devices by regex; dnl # and currently have no other use for the library: AC_SEARCH_LIBS(regcomp, regex) ]) AC_LANG_POP([C]) + AS_IF([test x"${nut_with_usb_busport}" = xyes], [ + AC_DEFINE(WITH_USB_BUSPORT, 1, + [Define to 1 for libusb versions where we can support "busport" USB matching value.]) + ], [ + AC_DEFINE(WITH_USB_BUSPORT, 0, + [Define to 1 for libusb versions where we can support "busport" USB matching value.]) + ]) + AS_IF([test "${nut_have_libusb}" = "yes"], [ LIBUSB_CFLAGS="${CFLAGS}" LIBUSB_LIBS="${LIBS}" From cee9d327b3255cca52e01b7bf1af214ef41a0781 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:57:10 +0200 Subject: [PATCH 1039/1232] USB driver: adjust to WITH_USB_BUSPORT normally being always defined, just not always active [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 4 ++-- drivers/libshut.c | 6 +++--- drivers/libusb0.c | 6 +++--- drivers/libusb1.c | 10 +++++----- drivers/nutdrv_qx.c | 6 +++--- drivers/riello_usb.c | 4 ++-- drivers/tripplite_usb.c | 4 ++-- drivers/usb-common.c | 4 ++-- drivers/usb-common.h | 4 ++-- drivers/usbhid-ups.c | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 53f202a1b7..2bc9c28258 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -609,7 +609,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -# ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); # else if (getval("busport")) { @@ -732,7 +732,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -# ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); # endif #endif /* TESTING */ diff --git a/drivers/libshut.c b/drivers/libshut.c index ae48dc67ba..3601c0c344 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -468,7 +468,7 @@ static int libshut_open( free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -477,7 +477,7 @@ static int libshut_open( curDevice->ProductID = dev_descriptor->idProduct; curDevice->Bus = strdup("serial"); curDevice->Device = strdup(arg_device_path); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); @@ -529,7 +529,7 @@ static int libshut_open( upsdebugx(2, "- Product: %s", curDevice->Product); upsdebugx(2, "- Serial Number: %s", curDevice->Serial); upsdebugx(2, "- Bus: %s", curDevice->Bus); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 8318301fe1..86072bbba7 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -292,7 +292,7 @@ static int libusb_open(usb_dev_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -306,7 +306,7 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); @@ -364,7 +364,7 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 3e68571d1c..84d5ebdbc3 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -67,7 +67,7 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" -#ifndef WITH_USB_BUSPORT +#if (!defined WITH_USB_BUSPORT) || (!WITH_USB_BUSPORT) /* Not supported by this version of libusb1, * but let's not crash config parsing on * unknown keywords due to such nuances! :) @@ -172,7 +172,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; uint8_t bus_num, device_addr; -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) uint8_t bus_port; #endif int ret, res; @@ -249,7 +249,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -293,7 +293,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, } } -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) bus_port = libusb_get_port_number(device); curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { @@ -372,7 +372,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown"); upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index f136d9d948..f394ce5213 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3016,7 +3016,7 @@ void upsdrv_initups(void) getval("serial") || getval("bus") || getval("langid_fix") -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) || getval("busport") #endif ) { @@ -3124,7 +3124,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); # else if (getval("busport")) { @@ -3294,7 +3294,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); # endif diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index e85c208e8a..1a7fe7d4f3 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -864,7 +864,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #else if (getval("busport")) { @@ -1240,7 +1240,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); #endif } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 0f767e6fac..858b93dcd0 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1582,7 +1582,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); /* probably won't see this */ regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #endif @@ -1659,7 +1659,7 @@ void upsdrv_cleanup(void) free(curDevice.Serial); free(curDevice.Bus); free(curDevice.Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice.BusPort); #endif } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 7e5a307945..d3bc96748b 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -119,7 +119,7 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) return 0; } #endif -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) #ifdef DEBUG_EXACT_MATCH_BUSPORT if (strcmp_null(hd->BusPort, data->BusPort) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", @@ -400,7 +400,7 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) return r; } -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) r = match_regex(data->regex[7], hd->BusPort); if (r != 1) { /* diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 5f94697b7d..d1de6d23d5 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -460,7 +460,7 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) # define USBMATCHER_REGEXP_ARRAY_LIMIT 8 #else # define USBMATCHER_REGEXP_ARRAY_LIMIT 7 @@ -487,7 +487,7 @@ typedef struct USBDevice_s { char *Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) char *BusPort; /*!< Port name, e.g. "001" */ #endif } USBDevice_t; diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index d83f989e3c..7a7ab370e0 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1054,7 +1054,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #else if (getval("busport")) { @@ -1184,7 +1184,7 @@ void upsdrv_cleanup(void) free(curDevice.Serial); free(curDevice.Bus); free(curDevice.Device); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice.BusPort); # endif #endif /* !SHUT_MODE => USB */ From d450a563f888dcb05b6cb0bacef8ca5d0d1b932b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 20:20:32 +0200 Subject: [PATCH 1040/1232] tools/nut-scanner/scan_usb.c: add support for "busport" discovery where possible [#2043] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_usb.c | 78 ++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 2a8c116bfe..a56c54cf8a 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -54,6 +54,7 @@ static int (*nut_usb_get_string_simple)(libusb_device_handle *dev, int index, static void (*nut_usb_free_device_list)(libusb_device **list, int unref_devices); 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, struct libusb_device_descriptor *desc); #else /* => WITH_LIBUSB_0_1 */ @@ -157,6 +158,20 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + /* This method may be absent in some libusb versions, and we should + * tolerate that! In run-time driver code see also blocks fenced by: + * #if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + */ + *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, + "libusb_get_port_number"); + if ((dl_error = lt_dlerror()) != NULL) { + fprintf(stderr, + "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " + "The \"busport\" USB matching option will be disabled.\n", + libname_path, dl_error); + nut_usb_get_port_number = NULL; + } + *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { @@ -251,7 +266,8 @@ nutscan_device_t * nutscan_scan_usb() /* device_port physical meaning: connection port on that bus; * different consumers plugged into same socket should have * the same port value. However in practice such functionality - * depends on platform and HW involved. + * depends on platform and HW involved and may mean logical + * enumeration results. * In libusb1 API: first libusb_get_port_numbers() earlier known * as libusb_get_port_path() for physical port number on the bus, see * https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html#ga14879a0ea7daccdcddb68852d86c00c4 @@ -267,6 +283,12 @@ nutscan_device_t * nutscan_scan_usb() libusb_device *dev; libusb_device **devlist; uint8_t bus_num; + /* Sort of like device_port above, but different (should be + * more closely about physical port number than logical device + * enumeration results). Uses libusb_get_port_number() where + * available in libusb (and hoping the OS and HW honour it). + */ + char *bus_port = NULL; #else /* => WITH_LIBUSB_0_1 */ struct usb_device *dev; struct usb_bus *bus; @@ -339,6 +361,22 @@ nutscan_device_t * nutscan_scan_usb() } } + if (nut_usb_get_port_number != NULL) { + bus_port = (char *)malloc(4); + if (bus_port == NULL) { + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } else { + uint8_t port_num = (*nut_usb_get_port_number)(dev); + if (port_num > 0) { + snprintf(bus_port, 4, "%03d", port_num); + } else { + snprintf(bus_port, 4, ".*"); + } + } + } + bcdDevice = dev_desc.bcdDevice; #else /* => WITH_LIBUSB_0_1 */ # ifndef WIN32 @@ -367,8 +405,8 @@ nutscan_device_t * nutscan_scan_usb() ret = (*nut_usb_open)(dev, &udev); if (!udev || ret != LIBUSB_SUCCESS) { fprintf(stderr, "Failed to open device " - "bus '%s' device/port '%s', skipping: %s\n", - busname, device_port, + "bus '%s' device/port '%s' bus/port '%s', skipping: %s\n", + busname, device_port, bus_port, (*nut_usb_strerror)(ret)); /* Note: closing is not applicable @@ -379,6 +417,10 @@ nutscan_device_t * nutscan_scan_usb() free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } continue; } @@ -405,6 +447,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -425,6 +471,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -446,6 +496,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -466,6 +520,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -520,6 +578,16 @@ nutscan_device_t * nutscan_scan_usb() "device", device_port); +#if WITH_LIBUSB_1_0 + if (bus_port) { + nutscan_add_option_to_device(nut_dev, + "busport", + bus_port); + free(bus_port); + bus_port = NULL; + } +#endif /* WITH_LIBUSB_1_0 */ + /* Not currently matched by drivers, hence commented for now: */ sprintf(string, "%04X", bcdDevice); nutscan_add_option_to_device(nut_dev, @@ -540,6 +608,10 @@ nutscan_device_t * nutscan_scan_usb() #else /* not WITH_LIBUSB_0_1 */ free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } } (*nut_usb_free_device_list)(devlist, 1); From e2699889506a1102dc40b3b24e7221352dbabfd4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 21:02:21 +0200 Subject: [PATCH 1041/1232] drivers/libshut.h: update with formal support of "busport" (no-op for serial mode) [#2043] Signed-off-by: Jim Klimov --- drivers/libshut.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/libshut.h b/drivers/libshut.h index 84da1af1ed..caa0780ce8 100644 --- a/drivers/libshut.h +++ b/drivers/libshut.h @@ -116,7 +116,7 @@ typedef int usb_ctrl_timeout_msec; /* in milliseconds */ /*! * SHUTDevice_t: Describe a SHUT device. This structure contains exactly - * the 5 pieces of information by which a SHUT device identifies + * the 5 or more pieces of information by which a SHUT device identifies * itself, so it serves as a kind of "fingerprint" of the device. This * information must be matched exactly when reopening a device, and * therefore must not be "improved" or updated by a client @@ -132,6 +132,9 @@ typedef struct SHUTDevice_s { char* Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + char *BusPort; /*!< Port name, e.g. "001" */ +#endif } SHUTDevice_t; /*! From b2c99e1f0e51542582534e9802b36d3d2277a31e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 21:04:43 +0200 Subject: [PATCH 1042/1232] drivers/usbhid-ups.c: initialize BusPort where used [#2043] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 7a7ab370e0..36748c66fb 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -118,7 +118,11 @@ static subdriver_t *subdriver = NULL; /* Global vars */ static HIDDevice_t *hd = NULL; -static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, 0, NULL }; +static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, 0, NULL +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + , NULL +#endif +}; static HIDDeviceMatcher_t *subdriver_matcher = NULL; #if !((defined SHUT_MODE) && SHUT_MODE) static HIDDeviceMatcher_t *exact_matcher = NULL; From d6bee3ae16e947d6269dea4ea7c21bc340717958 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 21:18:05 +0200 Subject: [PATCH 1043/1232] upsmon: add support for administrative "OFF" state [#2044] Based on patch by "Bomorav" posted at https://github.com/networkupstools/nut/issues/2044#issuecomment-1720752199 Signed-off-by: Jim Klimov --- clients/upsmon.c | 10 ++++++++-- clients/upsmon.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 8340677fcb..da1d919bda 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -586,6 +586,7 @@ static void ups_on_batt(utype_t *ups) do_notify(ups, NOTIFY_ONBATT); setflag(&ups->status, ST_ONBATT); clearflag(&ups->status, ST_ONLINE); + clearflag(&ups->status, ST_OFF); } static void ups_on_line(utype_t *ups) @@ -607,6 +608,7 @@ static void ups_on_line(utype_t *ups) setflag(&ups->status, ST_ONLINE); clearflag(&ups->status, ST_ONBATT); + clearflag(&ups->status, ST_OFF); } /* create the flag file if necessary */ @@ -987,7 +989,7 @@ static void recalc(void) /* crit = (FSD) || (OB & LB) > HOSTSYNC seconds */ if (is_ups_critical(ups)) upsdebugx(1, "Critical UPS: %s", ups->sys); - else + else if (!flag_isset(ups->status, ST_OFF)) val_ol += ups->pv; ups = ups->next; @@ -1927,7 +1929,11 @@ static void parse_status(utype_t *ups, char *status) upsreplbatt(ups); if (!strcasecmp(statword, "CAL")) ups_cal(ups); - + if (!strcasecmp(statword, "OFF")) { + setflag(&ups->status, ST_OFF); + clearflag(&ups->status, ST_ONLINE); + clearflag(&ups->status, ST_ONBATT); + } /* do it last to override any possible OL */ if (!strcasecmp(statword, "FSD")) ups_fsd(ups); diff --git a/clients/upsmon.h b/clients/upsmon.h index a7946addae..7421f9ac49 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -31,6 +31,7 @@ #define ST_LOGIN (1 << 5) /* we are logged into this UPS */ #define ST_CLICONNECTED (1 << 6) /* upscli_connect returned OK */ #define ST_CAL (1 << 7) /* UPS calibration in progress (CAL) */ +#define ST_OFF (1 << 8) /* UPS is off or on sleep (OFF) */ /* required contents of flag file */ #define SDMAGIC "upsmon-shutdown-file" From 3e50df91dc7dc08950fc0f150f35b8041c0996fc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 22:09:58 +0200 Subject: [PATCH 1044/1232] clients/upsmon.{c,h}: enhance with support of OFF and BYPASS state reporting (entry/exit) [#2044] Signed-off-by: Jim Klimov --- clients/upsmon.c | 84 ++++++++++++++++++++++++++++++++++++++++++++---- clients/upsmon.h | 11 ++++++- 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index da1d919bda..e1e4066722 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -561,13 +561,82 @@ static void ups_is_gone(utype_t *ups) /* now only complain if we haven't lately */ if ((now - ups->lastncwarn) > nocommwarntime) { - /* NOCOMM indicates a persistent condition */ do_notify(ups, NOTIFY_NOCOMM); ups->lastncwarn = now; } } +static void ups_is_off(utype_t *ups) +{ + if (flag_isset(ups->status, ST_OFF)) { /* no change */ + upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); + return; + } + + sleepval = pollfreqalert; /* bump up polling frequency */ + + ups->linestate = 0; + + upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); + + /* must have changed from !OFF to OFF, so notify */ + + do_notify(ups, NOTIFY_OFF); + setflag(&ups->status, ST_OFF); + clearflag(&ups->status, ST_ONLINE); +} + +static void ups_is_notoff(utype_t *ups) +{ + /* Called when OFF is NOT among known states */ + if (flag_isset(ups->status, ST_OFF)) { /* actual change */ + do_notify(ups, NOTIFY_NOTOFF); + clearflag(&ups->status, ST_OFF); + + if (!flag_isset(ups->status, ST_ONBATT)) { + sleepval = pollfreq; + ups->linestate = 1; + setflag(&ups->status, ST_ONLINE); + } + } +} + +static void ups_is_bypass(utype_t *ups) +{ + if (flag_isset(ups->status, ST_BYPASS)) { /* no change */ + upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); + return; + } + + sleepval = pollfreqalert; /* bump up polling frequency */ + + ups->linestate = 0; /* if we lose comms, consider it AWOL */ + + upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); + + /* must have changed from !BYPASS to BYPASS, so notify */ + + do_notify(ups, NOTIFY_BYPASS); + setflag(&ups->status, ST_BYPASS); + clearflag(&ups->status, ST_ONLINE); +} + +static void ups_is_notbypass(utype_t *ups) +{ + /* Called when BYPASS is NOT among known states */ + if (flag_isset(ups->status, ST_BYPASS)) { /* actual change */ + do_notify(ups, NOTIFY_NOTBYPASS); + clearflag(&ups->status, ST_BYPASS); + + if (!flag_isset(ups->status, ST_ONBATT)) { + sleepval = pollfreq; + ups->linestate = 1; + setflag(&ups->status, ST_ONLINE); + } + } +} + static void ups_on_batt(utype_t *ups) { if (flag_isset(ups->status, ST_ONBATT)) { /* no change */ @@ -1908,6 +1977,10 @@ static void parse_status(utype_t *ups, char *status) clearflag(&ups->status, ST_LOWBATT); if (!strstr(status, "FSD")) clearflag(&ups->status, ST_FSD); + if (!strstr(status, "OFF")) + ups_is_notoff(ups); + if (!strstr(status, "BYPASS")) + ups_is_notbypass(ups); statword = status; @@ -1929,11 +2002,10 @@ static void parse_status(utype_t *ups, char *status) upsreplbatt(ups); if (!strcasecmp(statword, "CAL")) ups_cal(ups); - if (!strcasecmp(statword, "OFF")) { - setflag(&ups->status, ST_OFF); - clearflag(&ups->status, ST_ONLINE); - clearflag(&ups->status, ST_ONBATT); - } + if (!strcasecmp(statword, "OFF")) + ups_is_off(ups); + if (!strcasecmp(statword, "BYPASS")) + ups_is_bypass(ups); /* do it last to override any possible OL */ if (!strcasecmp(statword, "FSD")) ups_fsd(ups); diff --git a/clients/upsmon.h b/clients/upsmon.h index 7421f9ac49..c1ed5ffd08 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -31,7 +31,8 @@ #define ST_LOGIN (1 << 5) /* we are logged into this UPS */ #define ST_CLICONNECTED (1 << 6) /* upscli_connect returned OK */ #define ST_CAL (1 << 7) /* UPS calibration in progress (CAL) */ -#define ST_OFF (1 << 8) /* UPS is off or on sleep (OFF) */ +#define ST_OFF (1 << 8) /* UPS is administratively off or asleep (OFF) */ +#define ST_BYPASS (1 << 9) /* UPS is on bypass so not protecting */ /* required contents of flag file */ #define SDMAGIC "upsmon-shutdown-file" @@ -88,6 +89,10 @@ typedef struct { #define NOTIFY_NOCOMM 8 /* UPS hasn't been contacted in a while */ #define NOTIFY_NOPARENT 9 /* privileged parent process died */ #define NOTIFY_CAL 10 /* UPS is performing calibration */ +#define NOTIFY_OFF 11 /* UPS is administratively OFF or asleep*/ +#define NOTIFY_NOTOFF 12 /* UPS is not anymore administratively OFF or asleep*/ +#define NOTIFY_BYPASS 13 /* UPS is administratively on bypass */ +#define NOTIFY_NOTBYPASS 14 /* UPS is not anymore administratively on bypass */ /* notify flag values */ @@ -128,6 +133,10 @@ static struct { { NOTIFY_NOCOMM, "NOCOMM", NULL, "UPS %s is unavailable", NOTIFY_DEFAULT }, { NOTIFY_NOPARENT, "NOPARENT", NULL, "upsmon parent process died - shutdown impossible", NOTIFY_DEFAULT }, { NOTIFY_CAL, "CAL", NULL, "UPS %s: calibration in progress", NOTIFY_DEFAULT }, + { NOTIFY_OFF, "OFF", NULL, "UPS %s: administratively OFF or asleep", NOTIFY_DEFAULT }, + { NOTIFY_NOTOFF, "NOTOFF", NULL, "UPS %s: no longer administratively OFF or asleep", NOTIFY_DEFAULT }, + { NOTIFY_BYPASS, "BYPASS", NULL, "UPS %s: on bypass (powered, not protecting)", NOTIFY_DEFAULT }, + { NOTIFY_NOTBYPASS,"NOTBYPASS",NULL, "UPS %s: no longer on bypass", NOTIFY_DEFAULT }, { 0, NULL, NULL, NULL, 0 } }; From b7b0cd09d5fcdee9674a140c47a7fbbdc99c2856 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 22:14:37 +0200 Subject: [PATCH 1045/1232] NEWS.adoc: upsmon now handles OFF and BYPASS states [#2044] Signed-off-by: Jim Klimov --- NEWS.adoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index 171eb2349b..814bc79ff6 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -351,6 +351,15 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. remains mounted at least read-only late in shutdown) and a new optional POLLFAIL_LOG_THROTTLE_MAX setting [#529, #506] + - Also `upsmon` should now recognize `OFF` and `BYPASS` flags in `ups.status` + and report that these states begin or end. The `OFF` state usually means + than an administrative action happened to power off the load, but the UPS + device is still alive and communicating (USB, SNMP, etc.); corresponding + `MONITOR`'ed amount of power sources are considered not being "fed" for + the power value calculation purposes. The `BYPASS` state is now treated + similarly to `ONBATT`: currently this UPS "feeds" its load, but if later + communications fail, it is considered dead. [#2044] + - Extended Linux systemd support with optional notifications about daemon state (READY, RELOADING, STOPPING) and watchdog keep-alive messages [#1590] From eb8db85ab0d75e37d06531b24eb0e90306f1b642 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 22:32:06 +0200 Subject: [PATCH 1046/1232] upsmon(.conf) docs and samples - update for new notification types [#2044 and before] Signed-off-by: Jim Klimov --- conf/upsmon.conf.sample.in | 5 +++++ docs/man/upsmon.conf.txt | 12 ++++++++++++ docs/man/upsmon.txt | 19 +++++++++++++++++++ docs/nut.dict | 4 +++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 4f4ca1e56a..0bb4c501a9 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -280,6 +280,11 @@ POWERDOWNFLAG "@POWERDOWNFLAG@" # NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" # NOTIFYMSG NOCOMM "UPS %s is unavailable" # NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible" +# NOTIFYMSG CAL "UPS %s: calibration in progress" +# NOTIFYMSG OFF "UPS %s: administratively OFF or asleep" +# NOTIFYMSG NOTOFF "UPS %s: no longer administratively OFF or asleep" +# NOTIFYMSG BYPASS "UPS %s: on bypass (powered, not protecting)" +# NOTIFYMSG NOTBYPASS "UPS %s: no longer on bypass" # # Note that %s is replaced with the identifier of the UPS in question. # diff --git a/docs/man/upsmon.conf.txt b/docs/man/upsmon.conf.txt index 2ebd18f419..0997c9ea0e 100644 --- a/docs/man/upsmon.conf.txt +++ b/docs/man/upsmon.conf.txt @@ -238,6 +238,18 @@ REPLBATT;; The UPS battery is bad and needs to be replaced NOCOMM;; A UPS is unavailable (can't be contacted for monitoring) +NOPARENT;; `upsmon` parent process died - shutdown impossible + +CAL;; UPS calibration in progress + +OFF;; UPS administratively OFF or asleep + +NOTOFF;; UPS no longer administratively OFF or asleep + +BYPASS;; UPS on bypass (powered, not protecting) + +NOTBYPASS;; UPS no longer on bypass + *NOTIFYFLAG* 'type' 'flag'[+'flag']...:: By default, upsmon sends walls global messages to all logged in users) diff --git a/docs/man/upsmon.txt b/docs/man/upsmon.txt index 6aa35d0ba3..464ba705f6 100644 --- a/docs/man/upsmon.txt +++ b/docs/man/upsmon.txt @@ -157,6 +157,25 @@ The UPS needs to have its battery replaced. *NOCOMM*:: The UPS can't be contacted for monitoring. +*NOPARENT*:: +`upsmon` parent process died - shutdown impossible. + +*CAL*:: +UPS calibration in progress. + +*OFF*:: +UPS administratively OFF or asleep. + +*NOTOFF*:: +UPS no longer administratively OFF or asleep. + +*BYPASS*:: +UPS on bypass (powered, not protecting). + +*NOTBYPASS*:: +UPS no longer on bypass. + + NOTIFY COMMAND -------------- diff --git a/docs/nut.dict b/docs/nut.dict index 34573c555a..9a2bc36a82 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3222 utf-8 +personal_ws-1.1 en 3224 utf-8 AAS ABI ACFAIL @@ -767,10 +767,12 @@ NONBLOCK NONUT NOP NOPARENT +NOTBYPASS NOTIFYCMD NOTIFYFLAG NOTIFYFLAGS NOTIFYMSG +NOTOFF NQA NTP NUT's From 83d241f3eed71dd7da4c8b1fb5425290b816a183 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 00:41:43 +0200 Subject: [PATCH 1047/1232] scripts/augeas/nutupsmonconf.aug.in: update for new notification types [#2044 and before] Signed-off-by: Jim Klimov --- scripts/augeas/nutupsmonconf.aug.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/augeas/nutupsmonconf.aug.in b/scripts/augeas/nutupsmonconf.aug.in index e3941764a2..712d81e520 100644 --- a/scripts/augeas/nutupsmonconf.aug.in +++ b/scripts/augeas/nutupsmonconf.aug.in @@ -91,6 +91,11 @@ let upsmon_notify_type = "ONLINE" | "REPLBATT" | "NOCOMM" | "NOPARENT" + | "CAL" + | "OFF" + | "NOTOFF" + | "BYPASS" + | "NOTBYPASS" let upsmon_notify = [ del_spc . key "NOTIFYMSG" . sep_spc . [ label "type" . store upsmon_notify_type . sep_spc ] From 573f93b61d31036daa6c84e3c85284cb8b1e6690 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 00:47:21 +0200 Subject: [PATCH 1048/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: detect USB drivers by "busport" among config options [#2043] Signed-off-by: Jim Klimov --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index b237c03423..2d2c126dbb 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -490,7 +490,7 @@ upsconf_getDriverMedia() { printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; /dev/*) # See drivers/nutdrv_qx.c :: upsdrv_initups() for a list - if [ -n "`upsconf_getValue "$1" 'subdriver' 'vendorid' 'productid' 'vendor' 'product' 'serial' 'bus' 'langid_fix'`" ] \ + if [ -n "`upsconf_getValue "$1" 'subdriver' 'vendorid' 'productid' 'vendor' 'product' 'serial' 'bus' 'busport' 'langid_fix'`" ] \ ; then printf '%s\n%s\n' "$CURR_DRV" "usb" ; return else From d00e5e012cd95e4e960f551587ed09e7f2d82c4f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 02:56:22 +0200 Subject: [PATCH 1049/1232] Fightwarn: numerous complaints from clang-15 [#823] Surprised that so many of these were not found sooner. Almost all fall into a few simple categories: * method(void) declared without a "void" * declarations after code ** NUT_UNUSED_VARIABLE() is code ** scoping in switch() cases * a few smartly detected unused variables => added reasonable use-cases (logging or better) Signed-off-by: Jim Klimov --- NEWS.adoc | 2 + clients/cgilib.c | 3 +- clients/upsclient.c | 9 ++- clients/upslog.c | 8 +- clients/upsmon.c | 3 +- clients/upsset.c | 3 +- common/common.c | 5 +- drivers/adelsystem_cbi.c | 60 +++++++++------ drivers/al175.c | 52 +++++++------ drivers/bcmxcp.c | 6 +- drivers/bcmxcp_ser.c | 2 +- drivers/bestuferrups.c | 2 +- drivers/blazer_usb.c | 6 +- drivers/dstate.c | 20 +++-- drivers/eaton-pdu-marlin-mib.c | 2 +- drivers/ever-hid.c | 105 ++++++++++++------------- drivers/generic_modbus.c | 2 +- drivers/hidparser.c | 8 +- drivers/hpe-pdu-mib.c | 2 +- drivers/libusb0.c | 3 +- drivers/mge-hid.c | 3 +- drivers/mge-utalk.c | 4 +- drivers/mge-xml.c | 12 +-- drivers/netxml-ups.c | 32 ++++---- drivers/nut-libfreeipmi.c | 4 +- drivers/nutdrv_atcl_usb.c | 20 ++--- drivers/nutdrv_qx.c | 57 ++++++++------ drivers/nutdrv_qx_ablerex.c | 36 +++++---- drivers/nutdrv_qx_bestups.c | 4 +- drivers/nutdrv_qx_masterguard.c | 13 ++-- drivers/nutdrv_siemens_sitop.c | 2 +- drivers/phoenixcontact_modbus.c | 4 +- drivers/pijuice.c | 39 +++++----- drivers/richcomm_usb.c | 26 ++++--- drivers/riello.c | 2 +- drivers/riello_ser.c | 12 +-- drivers/riello_usb.c | 12 +-- drivers/snmp-ups.c | 106 ++++++++++++++++---------- drivers/socomec_jbus.c | 8 +- drivers/solis.c | 12 +-- drivers/tripplite.c | 3 +- drivers/tripplite_usb.c | 80 +++++++++---------- drivers/tripplitesu.c | 3 +- drivers/upsdrvctl.c | 6 +- drivers/upsdrvquery.c | 23 +++--- server/netssl.c | 10 ++- server/upsd.c | 3 +- tests/getvaluetest.c | 14 ++-- tests/nuttimetest.c | 6 +- tools/nut-scanner/nut-scanner.c | 9 ++- tools/nut-scanner/nutscan-device.c | 2 +- tools/nut-scanner/nutscan-init.c | 4 +- tools/nut-scanner/nutscan-ip.c | 3 +- tools/nut-scanner/scan_eaton_serial.c | 3 +- tools/nut-scanner/scan_nut.c | 3 +- tools/nut-scanner/scan_snmp.c | 7 +- tools/nut-scanner/scan_usb.c | 11 ++- tools/nut-scanner/scan_xml_http.c | 19 +++-- 58 files changed, 526 insertions(+), 394 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 73dc1b49f6..5b16b191ea 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -113,6 +113,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * Something about compile-time macros or other warnings-related refactoring seems to have confused the MGE SHUT (Serial HID UPS Transfer) driver support [#2022] + * Some warnings were not detected by the tools or build scenarios used + earlier, and only got addressed now - An issue was identified which could cause `libupsclient` parser of device and host names to crash upon bad inputs (e.g. poorly resolved environment diff --git a/clients/cgilib.c b/clients/cgilib.c index 88cebfacb0..09606ad04c 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -40,6 +40,7 @@ static char *unescape(char *buf) ch = ' '; if (ch == '%') { + long l; if (i + 2 > buflen) fatalx(EXIT_FAILURE, "string too short for escaped char"); hex[0] = buf[++i]; @@ -48,7 +49,7 @@ static char *unescape(char *buf) if (!isxdigit((unsigned char) hex[0]) || !isxdigit((unsigned char) hex[1])) fatalx(EXIT_FAILURE, "bad escape char"); - long l = strtol(hex, NULL, 16); + l = strtol(hex, NULL, 16); assert(l>=0); assert(l<=255); ch = (char)l; /* FIXME: Loophole about non-ASCII symbols in top 128 values, or negatives for signed char... */ diff --git a/clients/upsclient.c b/clients/upsclient.c index cd30fedf67..22604a9ada 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -329,6 +329,7 @@ static void HandshakeCallback(PRFileDesc *fd, UPSCONN_t *client_data) int upscli_init(int certverify, const char *certpath, const char *certname, const char *certpasswd) { + const char *quiet_init_ssl; #ifdef WITH_OPENSSL long ret; int ssl_mode = SSL_VERIFY_NONE; @@ -343,7 +344,7 @@ int upscli_init(int certverify, const char *certpath, NUT_UNUSED_VARIABLE(certpasswd); #endif /* WITH_OPENSSL | WITH_NSS */ - const char *quiet_init_ssl = getenv("NUT_QUIET_INIT_SSL"); + quiet_init_ssl = getenv("NUT_QUIET_INIT_SSL"); if (quiet_init_ssl != NULL) { if (*quiet_init_ssl == '\0' || (strncmp(quiet_init_ssl, "true", 4) @@ -678,8 +679,9 @@ static ssize_t net_read(UPSCONN_t *ups, char *buf, size_t buflen, const time_t t * 32-bit builds)... Not likely to exceed in 64-bit builds, * but smaller systems with 16-bits might be endangered :) */ + int iret; assert(buflen <= INT_MAX); - int iret = SSL_read(ups->ssl, buf, (int)buflen); + iret = SSL_read(ups->ssl, buf, (int)buflen); assert(iret <= SSIZE_MAX); ret = (ssize_t)iret; #elif defined(WITH_NSS) /* WITH_OPENSSL */ @@ -762,8 +764,9 @@ static ssize_t net_write(UPSCONN_t *ups, const char *buf, size_t buflen, const t * 32-bit builds)... Not likely to exceed in 64-bit builds, * but smaller systems with 16-bits might be endangered :) */ + int iret; assert(buflen <= INT_MAX); - int iret = SSL_write(ups->ssl, buf, (int)buflen); + iret = SSL_write(ups->ssl, buf, (int)buflen); assert(iret <= SSIZE_MAX); ret = (ssize_t)iret; #elif defined(WITH_NSS) /* WITH_OPENSSL */ diff --git a/clients/upslog.c b/clients/upslog.c index f2a8cd95c6..502f6299e9 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -559,9 +559,9 @@ int main(int argc, char **argv) monhost_ups_anchor = monhost_ups_current; monhost_ups_current->next = NULL; monhost_ups_current->monhost = monhost; - monhost_len=1; + monhost_len = 1; } else { - fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s "); + fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s or -m "); } if (logfn) @@ -574,6 +574,10 @@ int main(int argc, char **argv) if (!logformat) fatalx(EXIT_FAILURE, "No format defined - but this should be impossible"); + /* shouldn't happen */ + if (!monhost_len) + fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s or -m "); + for (monhost_ups_current = monhost_ups_anchor; monhost_ups_current != NULL; monhost_ups_current = monhost_ups_current->next) { diff --git a/clients/upsmon.c b/clients/upsmon.c index 8340677fcb..0e29f89873 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1182,6 +1182,7 @@ static void addups(int reloading, const char *sys, const char *pvs, { unsigned int pv; utype_t *tmp, *last; + long lpv; /* the username is now required - no more host-based auth */ @@ -1191,7 +1192,7 @@ static void addups(int reloading, const char *sys, const char *pvs, return; } - long lpv = strtol(pvs, (char **) NULL, 10); + lpv = strtol(pvs, (char **) NULL, 10); #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_UNREACHABLE_CODE) ) # pragma GCC diagnostic push diff --git a/clients/upsset.c b/clients/upsset.c index 7339f9be70..f9f94228c9 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -751,11 +751,12 @@ static void do_type(const char *varname) if (!strncasecmp(answer[i], "STRING:", 7)) { char *ptr, len; + long l; /* split out the : data */ ptr = strchr(answer[i], ':'); *ptr++ = '\0'; - long l = strtol(ptr, (char **) NULL, 10); + l = strtol(ptr, (char **) NULL, 10); assert(l <= 127); /* FIXME: Loophole about longer numbers? Why are we limited to char at all here? */ len = (char)l; diff --git a/common/common.c b/common/common.c index f96584db60..d91a9d368f 100644 --- a/common/common.c +++ b/common/common.c @@ -78,7 +78,7 @@ const char *UPS_VERSION = NUT_VERSION_MACRO; #include #include #include -pid_t get_max_pid_t() +pid_t get_max_pid_t(void) { #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE #pragma GCC diagnostic push @@ -1948,9 +1948,10 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l #if !HAVE_DECL_REALPATH struct stat st; #endif + int compres; upsdebugx(5,"Comparing lib %s with dirpath entry %s", base_libname, dirp->d_name); - int compres = strncmp(dirp->d_name, base_libname, base_libname_length); + compres = strncmp(dirp->d_name, base_libname, base_libname_length); if (compres == 0 && dirp->d_name[base_libname_length] == '\0' /* avoid "*.dll.a" etc. */ ) { diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index c64da36343..3f2135b932 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -900,13 +900,16 @@ int get_dev_state(devreg_t regindx, devstate_t **dvstat) case LVDC: /* "output.voltage" */ case LCUR: /* "output.current" */ if (reg_val != 0) { + char *fval_s; + double fval; + state->reg.val.ui16 = reg_val; - double fval = reg_val / 1000.00; /* convert mV to V, mA to A */ + fval = reg_val / 1000.00; /* convert mV to V, mA to A */ n = snprintf(NULL, 0, "%.2f", fval); if (ptr != NULL) { free(ptr); } - char *fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); + fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); ptr = fval_s; sprintf(fval_s, "%.2f", fval); state->reg.strval = fval_s; @@ -921,12 +924,14 @@ int get_dev_state(devreg_t regindx, devstate_t **dvstat) case BCEF: case VAC: /* "input.voltage" */ if (reg_val != 0) { + char *reg_val_s; + state->reg.val.ui16 = reg_val; n = snprintf(NULL, 0, "%d", reg_val); if (ptr != NULL) { free(ptr); } - char *reg_val_s = (char *)xmalloc(sizeof(char) * (n + 1)); + reg_val_s = (char *)xmalloc(sizeof(char) * (n + 1)); ptr = reg_val_s; sprintf(reg_val_s, "%d", reg_val); state->reg.strval = reg_val_s; @@ -938,13 +943,16 @@ int get_dev_state(devreg_t regindx, devstate_t **dvstat) break; case BSOC: /* "battery.charge" */ if (reg_val != 0) { + double fval; + char *fval_s; + state->reg.val.ui16 = reg_val; - double fval = (double )reg_val * regs[BSOC].scale; + fval = (double )reg_val * regs[BSOC].scale; n = snprintf(NULL, 0, "%.2f", fval); if (ptr != NULL) { free(ptr); } - char *fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); + fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); ptr = fval_s; sprintf(fval_s, "%.2f", fval); state->reg.strval = fval_s; @@ -956,16 +964,21 @@ int get_dev_state(devreg_t regindx, devstate_t **dvstat) break; case BTMP: /* "battery.temperature" */ case OTMP: /* "ups.temperature" */ - state->reg.val.ui16 = reg_val; - double fval = reg_val - 273.15; - n = snprintf(NULL, 0, "%.2f", fval); - char *fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); - if (ptr != NULL) { - free(ptr); + { /* scoping */ + double fval; + char *fval_s; + + state->reg.val.ui16 = reg_val; + fval = reg_val - 273.15; + n = snprintf(NULL, 0, "%.2f", fval); + fval_s = (char *)xmalloc(sizeof(char) * (n + 1)); + if (ptr != NULL) { + free(ptr); + } + ptr = fval_s; + sprintf(fval_s, "%.2f", fval); + state->reg.strval = fval_s; } - ptr = fval_s; - sprintf(fval_s, "%.2f", fval); - state->reg.strval = fval_s; upsdebugx(3, "get_dev_state: variable: %s", state->reg.strval); break; case PMNG: /* "ups.status" & "battery.charge" */ @@ -1155,15 +1168,18 @@ int get_dev_state(devreg_t regindx, devstate_t **dvstat) * memory corruptions and buggy inputs below... */ default: - state->reg.val.ui16 = reg_val; - n = snprintf(NULL, 0, "%d", reg_val); - if (ptr != NULL) { - free(ptr); + { /* scoping */ + char *reg_val_s; + state->reg.val.ui16 = reg_val; + n = snprintf(NULL, 0, "%d", reg_val); + if (ptr != NULL) { + free(ptr); + } + reg_val_s = (char *)xmalloc(sizeof(char) * (n + 1)); + ptr = reg_val_s; + sprintf(reg_val_s, "%d", reg_val); + state->reg.strval = reg_val_s; } - char *reg_val_s = (char *)xmalloc(sizeof(char) * (n + 1)); - ptr = reg_val_s; - sprintf(reg_val_s, "%d", reg_val); - state->reg.strval = reg_val_s; break; #ifdef __clang__ # pragma clang diagnostic pop diff --git a/drivers/al175.c b/drivers/al175.c index 08b4b9b0df..6ed311a8dc 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -553,9 +553,9 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_ * begin end */ - int err; - size_t i; - const byte_t *reply = NULL; + int err; + size_t i, io_buf_len; + const byte_t *reply = NULL; /* 1: extract header and parse it */ /*const*/ raw_data_t raw_reply_head = raw_reply; @@ -578,7 +578,7 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_ } - /* extract the data */ + /* 3: extract the data */ if (io_buf->buf_size < io_head->len) { upsdebugx(3, "%s: too much data to fit in io_buf\t(%" PRIuSIZE " > %" PRIuSIZE ")", __func__, io_head->len, io_buf->buf_size); @@ -592,7 +592,7 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_ *(io_buf->end++) = reply[11+i]; assert(io_buf->end - io_buf->begin >= 0); - size_t io_buf_len = (size_t)(io_buf->end - io_buf->begin); + io_buf_len = (size_t)(io_buf->end - io_buf->begin); reverse_bits(io_buf->begin, io_buf_len ); upsdebug_hex(3, "\t\t--> payload", io_buf->begin, io_buf_len); @@ -670,14 +670,15 @@ static int al_check_ack(/*const*/ raw_data_t raw_ack) /* clear any flow control (copy from powercom.c) */ static void ser_disable_flow_control (void) { - struct termios tio; + struct termios tio; + tcflag_t x; tcgetattr (upsfd, &tio); /* Clumsy rewrite of a one-liner * tio.c_iflag &= ~ (IXON | IXOFF); * to avoid type conversion warnings */ - tcflag_t x = (IXON | IXOFF); + x = (IXON | IXOFF); tio.c_iflag &= ~ x; tio.c_cc[VSTART] = _POSIX_VDISABLE; tio.c_cc[VSTOP] = _POSIX_VDISABLE; @@ -688,7 +689,7 @@ static void ser_disable_flow_control (void) tcsetattr(upsfd, TCSANOW, &tio); } -static void flush_rx_queue() +static void flush_rx_queue(void) { ser_flush_in(upsfd, "", /*verbose=*/nut_debug_level); } @@ -702,10 +703,11 @@ static void flush_rx_queue() */ static int tx(const char *dmsg, /*const*/ raw_data_t frame) { - ssize_t err; + ssize_t err; + size_t frame_len; assert(frame.end - frame.begin >= 0); - size_t frame_len = (size_t)(frame.end - frame.begin); + frame_len = (size_t)(frame.end - frame.begin); upsdebug_ascii(3, dmsg, frame.begin, frame_len); @@ -807,9 +809,9 @@ static int scan_for(char c) * * @return 0 (ok) -1 (error) */ -static int recv_command_ack() +static int recv_command_ack(void) { - ssize_t err; + ssize_t err; raw_data_t ack; byte_t ack_buf[8]; @@ -855,12 +857,12 @@ static int recv_command_ack() */ static int recv_register_data(io_head_t *io, raw_data_t *io_buf) { - ssize_t err; - int ret; - raw_data_t reply_head; - raw_data_t reply; - - byte_t reply_head_buf[11]; + ssize_t err; + int ret; + size_t reply_head_len; + raw_data_t reply_head; + raw_data_t reply; + byte_t reply_head_buf[11]; /* 1: STX */ err = scan_for(STX); @@ -897,7 +899,7 @@ static int recv_register_data(io_head_t *io, raw_data_t *io_buf) reply = raw_xmalloc(11/*head*/ + io->len/*data*/ + 2/*ETX BCC*/); assert (reply_head.end - reply_head.begin >= 0); - size_t reply_head_len = (size_t)(reply_head.end - reply_head.begin); + reply_head_len = (size_t)(reply_head.end - reply_head.begin); memcpy(reply.end, reply_head.begin, reply_head_len); reply.end += reply_head_len; @@ -1053,9 +1055,9 @@ ACT SWITCH_TEMP_COMP (uint16_t on); ACT SWITCH_SYM_ALARM (void); /* Implement */ -ACT TOGGLE_PRS_ONOFF () { return al175_do(0x81, 0x80 Z3); } -ACT CANCEL_BOOST () { return al175_do(0x82, 0x80 Z3); } -ACT STOP_BATTERY_TEST () { return al175_do(0x83, 0x80 Z3); } +ACT TOGGLE_PRS_ONOFF (void) { return al175_do(0x81, 0x80 Z3); } +ACT CANCEL_BOOST (void) { return al175_do(0x82, 0x80 Z3); } +ACT STOP_BATTERY_TEST (void) { return al175_do(0x83, 0x80 Z3); } ACT START_BATTERY_TEST (VV_t EndVolt, mm_t Minutes) { return al175_do(0x83, 0x81, EndVolt, Minutes Z1); } @@ -1068,8 +1070,8 @@ ACT SET_DISCONNECT_LEVEL_AND_DELAY (VV_t level, mm_t delay) { return al175_do(0x87, 0x84, level, delay Z1); } -ACT RESET_ALARMS () { return al175_do(0x88, 0x80 Z3); } -ACT CHANGE_COMM_PROTOCOL () { return al175_do(0x89, 0x80 Z3); } +ACT RESET_ALARMS (void) { return al175_do(0x88, 0x80 Z3); } +ACT CHANGE_COMM_PROTOCOL (void) { return al175_do(0x89, 0x80 Z3); } ACT SET_VOLTAGE_AT_ZERO_T (VV_t v) { return al175_do(0x8a, 0x80, v Z2); } ACT SET_SLOPE_AT_ZERO_T (VV_t mv_per_degree) { return al175_do(0x8a, 0x81, mv_per_degree Z2); } @@ -1078,7 +1080,7 @@ ACT SET_MAX_TCOMP_VOLTAGE (VV_t v) { return al175_do(0x8a, 0x82, v Z2); } ACT SET_MIN_TCOMP_VOLTAGE (VV_t v) { return al175_do(0x8a, 0x83, v Z2); } ACT SWITCH_TEMP_COMP (uint16_t on) { return al175_do(0x8b, 0x80, on Z2); } -ACT SWITCH_SYM_ALARM () { return al175_do(0x8c, 0x80 Z3); } +ACT SWITCH_SYM_ALARM (void) { return al175_do(0x8c, 0x80 Z3); } /** diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index 958cefc5dd..fd6676ff9a 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -389,7 +389,7 @@ unsigned char calc_checksum(const unsigned char *buf) return c; } -void init_command_map() +void init_command_map(void) { int i = 0; @@ -442,7 +442,7 @@ void init_command_map() } } -void init_meter_map() +void init_meter_map(void) { /* Clean entire map */ memset(&bcmxcp_meter_map, 0, sizeof(BCMXCP_METER_MAP_ENTRY_t) * BCMXCP_METER_MAP_MAX); @@ -519,7 +519,7 @@ void init_meter_map() bcmxcp_meter_map[BCMXCP_METER_MAP_LINE_EVENT_COUNTER].nut_entity = "input.quality"; } -void init_alarm_map() +void init_alarm_map(void) { /* Clean entire map */ memset(&bcmxcp_alarm_map, 0, sizeof(BCMXCP_ALARM_MAP_ENTRY_t) * BCMXCP_ALARM_MAP_MAX); diff --git a/drivers/bcmxcp_ser.c b/drivers/bcmxcp_ser.c index 6979b7f9f1..c11f987e84 100644 --- a/drivers/bcmxcp_ser.c +++ b/drivers/bcmxcp_ser.c @@ -270,7 +270,7 @@ ssize_t command_write_sequence(unsigned char *command, size_t command_length, un return bytes_read; } -void upsdrv_comm_good() +void upsdrv_comm_good(void) { ser_comm_good(); } diff --git a/drivers/bestuferrups.c b/drivers/bestuferrups.c index 7ef36347cb..c248b13ba7 100644 --- a/drivers/bestuferrups.c +++ b/drivers/bestuferrups.c @@ -420,7 +420,7 @@ static void setup_serial(void) } -void upsdrv_initups () +void upsdrv_initups (void) { char temp[256], fcstring[512]; diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 2bc9c28258..27c5ceecbf 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -300,6 +300,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen) upsdebugx(1, "received %d (%d)", ret, buf[0]); if (langid_fix != -1) { + size_t di, si, size; /* Limit this check, at least for now */ /* Invalid receive size - message corrupted */ if (ret != buf[0]) @@ -311,7 +312,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen) /* Simple unicode -> ASCII inplace conversion * FIXME: this code is at least shared with mge-shut/libshut * Create a common function? */ - size_t di, si, size = (size_t)buf[0]; + size = (size_t)buf[0]; for (di = 0, si = 2; si < size; si += 2) { if (di >= (buflen - 1)) break; @@ -564,9 +565,10 @@ static const struct subdriver_t { void upsdrv_help(void) { #ifndef TESTING - printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: "); size_t i; + printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: "); + for (i = 0; subdriver[i].name != NULL; i++) { if (i>0) printf(", "); diff --git a/drivers/dstate.c b/drivers/dstate.c index 80435f08c0..6f50a935db 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -1592,11 +1592,13 @@ void alarm_set(const char *buf) * Note: LARGEBUF was the original limit mismatched vs alarm_buf * size before PR #986. */ - char alarm_tmp[LARGEBUF]; + char alarm_tmp[LARGEBUF]; + int ibuflen; + size_t buflen; + memset(alarm_tmp, 0, sizeof(alarm_tmp)); /* A bit of complexity to keep both (int)snprintf(...) and (size_t)sizeof(...) happy */ - int ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf); - size_t buflen; + ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf); if (ibuflen < 0) { alarm_tmp[0] = 'N'; alarm_tmp[1] = '/'; @@ -1632,10 +1634,12 @@ void alarm_set(const char *buf) upslogx(LOG_ERR, "%s: error setting alarm_buf to: %s%s", __func__, alarm_tmp, ( (buflen < sizeof(alarm_tmp)) ? "" : "..." ) ); } else if ((size_t)ret > sizeof(alarm_buf)) { - char alarm_tmp[LARGEBUF]; + char alarm_tmp[LARGEBUF]; + int ibuflen; + size_t buflen; + memset(alarm_tmp, 0, sizeof(alarm_tmp)); - int ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf); - size_t buflen; + ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf); if (ibuflen < 0) { alarm_tmp[0] = 'N'; alarm_tmp[1] = '/'; @@ -1932,9 +1936,11 @@ static int dstate_tree_dump(const st_tree_t *node) /* Public interface */ void dstate_dump(void) { + const st_tree_t *node; + upsdebugx(3, "Entering %s", __func__); - const st_tree_t *node = (const st_tree_t *)dstate_getroot(); + node = (const st_tree_t *)dstate_getroot(); dstate_tree_dump(node); } diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index 94b9af7a01..a49cf5beb2 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -380,7 +380,7 @@ static snmp_info_t eaton_marlin_mib[] = { { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, - /* FIXME: needs a date reformating callback + /* FIXME: needs a date reformatting callback * 2011-8-29,16:27:25.0,+1:0 * Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00 * { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, diff --git a/drivers/ever-hid.c b/drivers/ever-hid.c index 609b18076a..2bbe2405a5 100644 --- a/drivers/ever-hid.c +++ b/drivers/ever-hid.c @@ -59,7 +59,7 @@ static usb_device_id_t ever_usb_device_table[] = { static const char *ever_format_hardware_fun(double value) { - /*TODO - add exception handling for v1.0b0B */ + /* TODO - add exception handling for v1.0b0B */ const char* hard_rev[27] = {"0", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; static char model[10]; snprintf(model, sizeof(model), "rev.%sv%02u", @@ -70,8 +70,9 @@ static const char *ever_format_hardware_fun(double value) static const char *ever_format_version_fun(double value) { - /*upsdebugx(1, "UPS ups_firmware_conversion_fun VALUE: %d", (long)value ); */ static char model[10]; + + /*upsdebugx(1, "UPS ups_firmware_conversion_fun VALUE: %d", (long)value);*/ snprintf(model, sizeof(model), "v%X.%Xb%02d", ((unsigned int)value & 0xF000)>>12, ((unsigned int)value & 0xF00)>>8, @@ -81,18 +82,17 @@ static const char *ever_format_version_fun(double value) static const char *ever_mac_address_fun(double value) { + int mac_adress_report_id = 210; + int len = reportbuf->len[mac_adress_report_id]; + int n = 0; /* number of characters currently in line */ + int i; /* number of bytes output from buffer */ + const void *buf = reportbuf->data[mac_adress_report_id]; + static char line[100]; NUT_UNUSED_VARIABLE(value); - int mac_adress_report_id = 210; - int len = reportbuf->len[mac_adress_report_id]; - const void *buf = reportbuf->data[mac_adress_report_id]; - - static char line[100]; line[0] = '\0'; - int n = 0; /* number of characters currently in line */ - int i; /* number of bytes output from buffer */ - /* skip first elemnt which is a report id */ + /* skip first element which is a report id */ for (i = 1; i < len; i++) { n = snprintfcat(line, sizeof(line), n ? ":%02x" : "%02x", ((unsigned char *)buf)[i]); @@ -103,11 +103,14 @@ static const char *ever_mac_address_fun(double value) static const char *ever_ip_address_fun(double value) { + static int report_counter = 1; + int report_id = 211, len; + int n = 0; /* number of characters currently in line */ + int i; /* number of bytes output from buffer */ + const void *buf; + static char line[100]; NUT_UNUSED_VARIABLE(value); - static int report_counter = 1; - int report_id = 211; - if(report_counter == 1) report_id = 211; /* notification dest ip */ else if(report_counter == 2) @@ -119,15 +122,12 @@ static const char *ever_ip_address_fun(double value) report_counter== 4 ? report_counter=1 : report_counter++; - int len = reportbuf->len[report_id]; - const void *buf = reportbuf->data[report_id]; + len = reportbuf->len[report_id]; + buf = reportbuf->data[report_id]; - static char line[100]; line[0] = '\0'; - int n = 0; /* number of characters currently in line */ - int i; /* number of bytes output from buffer */ - /*skip first element which is a report id */ + /* skip first element which is a report id */ for (i = 1; i < len; i++) { n = snprintfcat(line, sizeof(line), n ? ".%d" : "%d", @@ -139,11 +139,12 @@ static const char *ever_ip_address_fun(double value) static const char *ever_packets_fun(double value) { + static int report_counter = 1; + int report_id = 215, len, res; + const unsigned char *buf; + static char line[200]; NUT_UNUSED_VARIABLE(value); - static int report_counter = 1; - int report_id = 215; - if(report_counter == 1 ) report_id = 215; else if(report_counter == 2 ) @@ -155,18 +156,17 @@ static const char *ever_packets_fun(double value) report_counter== 4 ? report_counter=1 : report_counter++; - int len = reportbuf->len[report_id]; - const unsigned char *buf = reportbuf->data[report_id]; + len = reportbuf->len[report_id]; + buf = reportbuf->data[report_id]; - static char line[100]; line[0] = '\0'; - /*skip first elemnt which is a report id */ + /* skip first element which is a report id */ if(len < 5) return ""; - int res = (int)buf[1]; + res = (int)buf[1]; res |= (int)buf[2] << 8; res |= (int)buf[3] << 16; res |= (int)buf[4] << 24; @@ -178,16 +178,15 @@ static const char *ever_packets_fun(double value) static const char* ever_workmode_fun(double value) { + int workmode_report_id = 74; + int workmode = -1; + const unsigned char *buf = reportbuf->data[workmode_report_id]; + static char line[200]; NUT_UNUSED_VARIABLE(value); - int workmode_report_id = 74; - int workmode = -1; - const unsigned char *buf = reportbuf->data[workmode_report_id]; - - static char line[100]; line[0] = '\0'; - /*skip first element which is a report id */ + /* skip first element which is a report id */ snprintfcat(line, sizeof(line), "%d", buf[1]); workmode = atoi(line); @@ -223,20 +222,18 @@ static const char* ever_workmode_fun(double value) static const char* ever_messages_fun(double value) { + int messages_report_id = 75, messages; + int n = 0; /* number of characters currently in line */ + const unsigned char *buf = reportbuf->data[messages_report_id]; + static char line[200]; NUT_UNUSED_VARIABLE(value); - int messages_report_id = 75; - const unsigned char *buf = reportbuf->data[messages_report_id]; - - static char line[200]; line[0] = '\0'; - /*skip first element which is a report id */ - int messages = (int)buf[1]; + /* skip first element which is a report id */ + messages = (int)buf[1]; messages |= (int)buf[2] << 8; - int n = 0; /* number of characters currently in line */ - /* duplicate of ups.status: OB LB */ /* if(messages & 0x01) @@ -271,21 +268,18 @@ static const char* ever_messages_fun(double value) static const char* ever_alarms_fun(double value) { + int alarms_report_id = 76, alarms; + int n = 0; /* number of characters currently in line */ + const unsigned char *buf = reportbuf->data[alarms_report_id]; + static char line[200]; NUT_UNUSED_VARIABLE(value); - int alarms_report_id = 76; - - const unsigned char *buf = reportbuf->data[alarms_report_id]; - - static char line[200]; line[0] = '\0'; - /*skip first element which is a report id */ - int alarms = (int)buf[1]; + /* skip first element which is a report id */ + alarms = (int)buf[1]; alarms |= (int)buf[2] << 8; - int n = 0; /* number of characters currently in line */ - if(alarms & 0x01) n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "OVERLOAD"); if(alarms & 0x02) @@ -308,16 +302,15 @@ static const char* ever_alarms_fun(double value) static const char* ever_on_off_fun(double value) { + int workmode_report_id = 74; + int workmode = -1; + const unsigned char *buf = reportbuf->data[workmode_report_id]; + static char line[200]; NUT_UNUSED_VARIABLE(value); - int workmode_report_id = 74; - int workmode = -1; - const unsigned char *buf = reportbuf->data[workmode_report_id]; - - static char line[100]; line[0] = '\0'; - /*skip first element which is a report id */ + /* skip first element which is a report id */ snprintfcat(line, sizeof(line), "%d", buf[1]); workmode = atoi(line); diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index d10472b452..b242c5a6a5 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -707,7 +707,7 @@ int get_signal_state(devstate_t state) } /* get driver configuration parameters */ -void get_config_vars() +void get_config_vars(void) { int i; /* local index */ diff --git a/drivers/hidparser.c b/drivers/hidparser.c index d77734eb9f..fd52fb3208 100644 --- a/drivers/hidparser.c +++ b/drivers/hidparser.c @@ -451,14 +451,16 @@ HIDData_t *FindObject_with_ID_Node(HIDDesc_t *pDesc_arg, uint8_t ReportID, HIDNo size_t i; for (i = 0; i < pDesc_arg->nitems; i++) { - HIDData_t *pData = &pDesc_arg->item[i]; + HIDData_t *pData = &pDesc_arg->item[i]; + HIDPath_t *pPath; + uint8_t size; if (pData->ReportID != ReportID) { continue; } - HIDPath_t * pPath = &pData->Path; - uint8_t size = pPath->Size; + pPath = &pData->Path; + size = pPath->Size; if (size == 0 || pPath->Node[size-1] != Node) { continue; } diff --git a/drivers/hpe-pdu-mib.c b/drivers/hpe-pdu-mib.c index 3f6c7dce70..a0b60adb3d 100644 --- a/drivers/hpe-pdu-mib.c +++ b/drivers/hpe-pdu-mib.c @@ -231,7 +231,7 @@ static snmp_info_t hpe_pdu_mib[] = { { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, - /* FIXME: needs a date reformating callback + /* FIXME: needs a date reformatting callback * 2011-8-29,16:27:25.0,+1:0 * Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00 * { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 86072bbba7..0dd46b0139 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -215,12 +215,13 @@ static int libusb_open(usb_dev_handle **udevp, usb_ctrl_char rdbuf[MAX_REPORT_SIZE]; usb_ctrl_charbufsize rdlen; + struct usb_bus *busses; + /* libusb base init */ usb_init(); usb_find_busses(); usb_find_devices(); - struct usb_bus *busses; #ifdef WIN32 busses = usb_get_busses(); #else diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index ba5dbc2ef0..2ae6f4f2ef 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -695,7 +695,6 @@ static info_lkp_t eaton_check_country_info[] = { * compute a realpower approximation using available data */ static const char *eaton_compute_realpower_fun(double value) { - NUT_UNUSED_VARIABLE(value); const char *str_ups_load = dstate_getinfo("ups.load"); const char *str_power_nominal = dstate_getinfo("ups.power.nominal"); const char *str_powerfactor = dstate_getinfo("output.powerfactor"); @@ -703,6 +702,8 @@ static const char *eaton_compute_realpower_fun(double value) int power_nominal = 0; int ups_load = 0; double realpower = 0; + NUT_UNUSED_VARIABLE(value); + if (str_power_nominal && str_ups_load) { /* Extract needed values */ ups_load = atoi(str_ups_load); diff --git a/drivers/mge-utalk.c b/drivers/mge-utalk.c index ec27989745..9e34954199 100644 --- a/drivers/mge-utalk.c +++ b/drivers/mge-utalk.c @@ -956,7 +956,9 @@ static ssize_t mge_command(char *reply, size_t replylen, const char *fmt, ...) bytes_rcvd = ser_get_line(upsfd, reply, replylen, MGE_REPLY_ENDCHAR, MGE_REPLY_IGNCHAR, 3, 0); - upsdebugx(4, "mge_command: received %" PRIiSIZE " byte(s)", bytes_rcvd); + upsdebugx(4, "mge_command: sent %" PRIiSIZE + ", received %" PRIiSIZE " byte(s)", + bytes_sent, bytes_rcvd); return bytes_rcvd; } diff --git a/drivers/mge-xml.c b/drivers/mge-xml.c index c676691cab..42eab857c7 100644 --- a/drivers/mge-xml.c +++ b/drivers/mge-xml.c @@ -1537,10 +1537,10 @@ subdriver_t mge_xml_subdriver = { }; const char *vname_nut2mge_xml(const char *name) { - assert(NULL != name); - size_t i = 0; + assert(NULL != name); + for (; i < sizeof(mge_xml2nut) / sizeof(xml_info_t); ++i) { xml_info_t *info = mge_xml2nut + i; @@ -1553,10 +1553,10 @@ const char *vname_nut2mge_xml(const char *name) { } const char *vname_mge_xml2nut(const char *name) { - assert(NULL != name); - size_t i = 0; + assert(NULL != name); + for (; i < sizeof(mge_xml2nut) / sizeof(xml_info_t); ++i) { xml_info_t *info = mge_xml2nut + i; @@ -1569,10 +1569,10 @@ const char *vname_mge_xml2nut(const char *name) { } char *vvalue_mge_xml2nut(const char *name, const char *value, size_t len) { - assert(NULL != name); - size_t i = 0; + assert(NULL != name); + for (; i < sizeof(mge_xml2nut) / sizeof(xml_info_t); ++i) { xml_info_t *info = mge_xml2nut + i; diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index f58d194e98..7ebc30432f 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -932,9 +932,8 @@ 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) { - NUT_UNUSED_VARIABLE(userdata); - char *val; + NUT_UNUSED_VARIABLE(userdata); upsdebugx(2, "%s: realm = [%s], attempt = %d", __func__, realm, attempt); @@ -1216,13 +1215,14 @@ static object_entry_t *set_object_add( const char *name, const char *value) { - char *name_cpy; - char *value_cpy; + char *name_cpy; + char *value_cpy; + object_entry_t *entry; assert(NULL != name); assert(NULL != value); - object_entry_t *entry = (object_entry_t *)calloc(1, + entry = (object_entry_t *)calloc(1, sizeof(object_entry_t)); if (NULL == entry) @@ -1297,13 +1297,15 @@ static object_query_status_t set_object_serialise_entries(ne_buffer *buff, objec static ne_buffer *set_object_serialise_raw(object_query_t *handle) { + ne_buffer *buff; + assert(NULL != handle); /* Sanity checks */ assert(SET_OBJECT_REQUEST == handle->type); /* Create buffer */ - ne_buffer *buff = ne_buffer_create(); + buff = ne_buffer_create(); /* neon API ref. states that the function always succeeds */ assert(NULL != buff); @@ -1316,7 +1318,8 @@ static ne_buffer *set_object_serialise_raw(object_query_t *handle) { static ne_buffer *set_object_serialise_form(object_query_t *handle) { - const char *vname = NULL; + const char *vname = NULL; + ne_buffer *buff; assert(NULL != handle); @@ -1324,7 +1327,7 @@ static ne_buffer *set_object_serialise_form(object_query_t *handle) { assert(SET_OBJECT_REQUEST == handle->type); /* Create buffer */ - ne_buffer *buff = ne_buffer_create(); + buff = ne_buffer_create(); /* neon API ref. states that the function always succeeds */ assert(NULL != buff); @@ -1562,18 +1565,20 @@ static int set_object_raw_resp_end_element( static object_query_t *set_object_deserialise_raw(ne_buffer *buff) { - int ne_status; + int ne_status; + object_query_t *handle; + ne_xml_parser *parser; assert(NULL != buff); /* Create SET_OBJECT query response */ - object_query_t *handle = object_query_create(SET_OBJECT_RESPONSE, RAW_POST); + handle = object_query_create(SET_OBJECT_RESPONSE, RAW_POST); if (NULL == handle) return NULL; /* Create XML parser */ - ne_xml_parser *parser = ne_xml_create(); + parser = ne_xml_create(); /* neon API ref. states that the function always succeeds */ assert(NULL != parser); @@ -1632,7 +1637,8 @@ static int send_http_request( assert(NULL != req); do { /* Pragmatic do ... while (0) loop allowing breaks on error */ - const ne_status *req_st; + const ne_status *req_st; + int status; /* Set Content-Type */ if (NULL != ct) @@ -1645,7 +1651,7 @@ static int send_http_request( req_body->data, req_body->used - 1); /* Send request */ - int status = ne_begin_request(req); + status = ne_begin_request(req); if (NE_OK != status) { break; diff --git a/drivers/nut-libfreeipmi.c b/drivers/nut-libfreeipmi.c index b37f58f06d..cdf3d59fb4 100644 --- a/drivers/nut-libfreeipmi.c +++ b/drivers/nut-libfreeipmi.c @@ -329,7 +329,7 @@ static float libfreeipmi_get_voltage (uint8_t voltage_code) } /* Cleanup IPMI contexts */ -static void libfreeipmi_cleanup() +static void libfreeipmi_cleanup(void) { /* cleanup */ if (fru_ctx) { @@ -842,7 +842,7 @@ Record ID, Sensor Name, Sensor Number, Sensor Type, Sensor State, Sensor Reading */ -int nut_ipmi_monitoring_init() +int nut_ipmi_monitoring_init(void) { int errnum; diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index b87a3eff35..c8d1162e2e 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -258,6 +258,17 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev { int ret = 0; uint8_t iManufacturer = 0, iProduct = 0, iSerialNumber = 0; +#if WITH_LIBUSB_1_0 + libusb_device **devlist; + ssize_t devcount = 0; + libusb_device_handle *handle; + struct libusb_device_descriptor dev_desc; + uint8_t bus_num; + /* TODO: consider device_addr */ + int i; +#else /* => WITH_LIBUSB_0_1 */ + struct usb_bus *bus; +#endif /* libusb base init */ #if WITH_LIBUSB_1_0 @@ -279,14 +290,6 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #endif #if WITH_LIBUSB_1_0 - libusb_device **devlist; - ssize_t devcount = 0; - libusb_device_handle *handle; - struct libusb_device_descriptor dev_desc; - uint8_t bus_num; - /* TODO: consider device_addr */ - int i; - devcount = libusb_get_device_list(NULL, &devlist); if (devcount <= 0) fatal_with_errno(EXIT_FAILURE, "No USB device found"); @@ -299,7 +302,6 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev ret = libusb_open(dev, &handle); *handlep = handle; #else /* => WITH_LIBUSB_0_1 */ - struct usb_bus *bus; for (bus = usb_busses; bus; bus = bus->next) { struct usb_device *dev; diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index f394ce5213..056130ef50 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -1039,6 +1039,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen) upsdebugx(1, "received %d (%d)", ret, buf[0]); if (langid_fix != -1) { + unsigned int di, si, size; /* Limit this check, at least for now */ /* Invalid receive size - message corrupted */ if (ret != buf[0]) { @@ -1049,7 +1050,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen) /* Simple unicode -> ASCII inplace conversion * FIXME: this code is at least shared with mge-shut/libshut * Create a common function? */ - unsigned int di, si, size = (unsigned int)buf[0]; + size = (unsigned int)buf[0]; for (di = 0, si = 2; si < size; si += 2) { if (di >= (buflen - 1)) @@ -1344,6 +1345,8 @@ static int hunnox_command(const char *cmd, char *buf, size_t buflen) /* if (hunnox_patch) { */ if (langid_fix != -1) { + unsigned int di, si, size; + /* Limit this check, at least for now */ /* Invalid receive size - message corrupted */ if (ret != buf[0]) { @@ -1354,7 +1357,7 @@ static int hunnox_command(const char *cmd, char *buf, size_t buflen) /* Simple unicode -> ASCII inplace conversion * FIXME: this code is at least shared with mge-shut/libshut * Create a common function? */ - unsigned int di, si, size = (unsigned int)buf[0]; + size = (unsigned int)buf[0]; for (di = 0, si = 2; si < size; si += 2) { if (di >= (buflen - 1)) break; @@ -1666,7 +1669,7 @@ static int snr_command(const char *cmd, char *buf, size_t buflen) } for (retry = 0; retry < 10; retry++) { - + unsigned int di, si, size; int ret; ret = usb_get_string(udev, @@ -1683,16 +1686,15 @@ static int snr_command(const char *cmd, char *buf, size_t buflen) /* This may serve in the future */ upsdebugx(1, "received %d (%d)", ret, buf[0]); - if (ret != buf[0]) { upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]); continue; } /* Simple unicode -> ASCII inplace conversion - * FIXME: this code is at least shared with mge-shut/libshut - * Create a common function? */ - unsigned int di, si, size = (unsigned int)buf[0]; + * FIXME: this code is at least shared with mge-shut/libshut + * Create a common function? */ + size = (unsigned int)buf[0]; for (di = 0, si = 2; si < size; si += 2) { if (di >= (buflen - 1)) @@ -1739,9 +1741,10 @@ static int snr_command(const char *cmd, char *buf, size_t buflen) static int ablerex_command(const char *cmd, char *buf, size_t buflen) { - int iii; + int iii; int len; - int idx; + int idx; + int retry; char tmp[64]; char tmpryy[64]; @@ -1753,8 +1756,6 @@ static int ablerex_command(const char *cmd, char *buf, size_t buflen) buflen = (INT_MAX - 1); } - int retry; - for (retry = 0; retry < 3; retry++) { int ret; @@ -2772,9 +2773,10 @@ void upsdrv_help(void) { #ifdef QX_USB #ifndef TESTING - printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: "); size_t i; + printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: "); + for (i = 0; usbsubdriver[i].name != NULL; i++) { if (i>0) printf(", "); @@ -3001,6 +3003,15 @@ void upsdrv_initinfo(void) /* Open the port and the like and choose the subdriver */ void upsdrv_initups(void) { +#ifdef QX_USB +# ifndef TESTING + int ret, langid; + char tbuf[255]; /* Some devices choke on size > 255 */ + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; + char *subdrv; +# endif +#endif + upsdebugx(1, "%s...", __func__); #if defined(QX_SERIAL) && defined(QX_USB) @@ -3034,6 +3045,8 @@ void upsdrv_initups(void) #ifdef QX_USB if (!is_usb) { + #else + { /* scoping */ #endif /* QX_USB */ #ifndef TESTING @@ -3101,6 +3114,8 @@ void upsdrv_initups(void) #ifdef QX_USB } else { /* is_usb */ + #else + } /* end of scoping */ #endif /* QX_USB */ #endif /* QX_SERIAL */ @@ -3108,14 +3123,10 @@ void upsdrv_initups(void) /* USB */ #ifdef QX_USB - warn_if_bad_usb_port_filename(device_path); + warn_if_bad_usb_port_filename(device_path); # ifndef TESTING - int ret, langid; - char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; - - char *subdrv = getval("subdriver"); + subdrv = getval("subdriver"); regex_array[0] = getval("vendorid"); regex_array[1] = getval("productid"); @@ -3315,6 +3326,10 @@ void upsdrv_cleanup(void) * Returns < 0 on error, 0 on timeout and the number of bytes read on success. */ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) { +#ifndef TESTING + ssize_t ret = -1; +#endif + /* NOTE: Could not find in which ifdef-ed codepath, but clang complained * about unused parameters here. Reference them just in case... */ @@ -3324,8 +3339,6 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) #ifndef TESTING - ssize_t ret = -1; - # ifdef QX_USB # ifdef QX_SERIAL @@ -3920,7 +3933,7 @@ static bool_t qx_ups_walk(walkmode_t mode) ) { if (getval("runtimecal")) { - + const char *val; time_t battery_now; time(&battery_now); @@ -3943,7 +3956,7 @@ static bool_t qx_ups_walk(walkmode_t mode) } - const char *val = dstate_getinfo("battery.voltage"); + val = dstate_getinfo("battery.voltage"); if (!val) { upsdebugx(2, "%s: unable to get battery.voltage", __func__); diff --git a/drivers/nutdrv_qx_ablerex.c b/drivers/nutdrv_qx_ablerex.c index f559ad0380..b22ac81eda 100755 --- a/drivers/nutdrv_qx_ablerex.c +++ b/drivers/nutdrv_qx_ablerex.c @@ -32,8 +32,10 @@ static int Q5_Vbc = -1; static int ablerexQ5Vb = -1; static int ablerex_Q5(item_t *item, char *value, const size_t valuelen) { + int Q5_Fout, Q5_Vb, Q5_O_Cur, Q5_Err; /* - int RawValue = 0; + //int Q5_InvW; + int RawValue = 0; RawValue = (unsigned char)item->value[0] * 256 + (unsigned char)item->value[1]; */ @@ -44,12 +46,12 @@ static int ablerex_Q5(item_t *item, char *value, const size_t valuelen) { upsdebugx(2, "Q52: %d %d %d %d %d %d", item->answer[6], item->answer[7], item->answer[8], item->answer[9], item->answer[10], item->answer[11]); upsdebugx(2, "Q53: %d %d %d %d", item->answer[12], item->answer[13], item->answer[14], item->answer[15]); - int Q5_Fout = (unsigned char)item->answer[1] * 256 + (unsigned char)item->answer[2]; - int Q5_Vb = (unsigned char)item->answer[7] * 256 + (unsigned char)item->answer[8]; + Q5_Fout = (unsigned char)item->answer[1] * 256 + (unsigned char)item->answer[2]; + Q5_Vb = (unsigned char)item->answer[7] * 256 + (unsigned char)item->answer[8]; Q5_Vbc = (unsigned char)item->answer[9] * 256 + (unsigned char)item->answer[10]; //int Q5_InvW = (unsigned char)item->answer[11] * 256 + (unsigned char)item->answer[12]; - int Q5_Err = (unsigned char)item->answer[13] * 256 + (unsigned char)item->answer[14]; - int Q5_O_Cur = (unsigned char)item->answer[15] * 256 + (unsigned char)item->answer[16]; + Q5_Err = (unsigned char)item->answer[13] * 256 + (unsigned char)item->answer[14]; + Q5_O_Cur = (unsigned char)item->answer[15] * 256 + (unsigned char)item->answer[16]; ablerexQ5Vb = Q5_Vb; upsdebugx(2, "Q5: %.1f %d %.1f", 0.1 * Q5_Fout, Q5_Err, 0.1 * Q5_O_Cur); @@ -86,7 +88,10 @@ static int ablerex_Q5(item_t *item, char *value, const size_t valuelen) { } static int ablerex_battery(item_t *item, char *value, const size_t valuelen) { - double BattV = 0.0; + double BattV = 0.0; + double nomBattV = 0.0; + double battvoltact = 0.0; + BattV = strtod(item->value, NULL); upsdebugx(2, "battvoltact2: %.2f", BattV); if (!dstate_getinfo("battery.voltage.nominal")) @@ -95,13 +100,10 @@ static int ablerex_battery(item_t *item, char *value, const size_t valuelen) { return 0; } - double nomBattV = 0.0; nomBattV = strtod(dstate_getinfo("battery.voltage.nominal"), NULL); upsdebugx(2, "battvoltact1: %.2f", nomBattV); //return 0; - double battvoltact = 0.0; - if (ablerexQ5Vb > 0) { battvoltact = ablerexQ5Vb * nomBattV / 1200; } else { @@ -174,7 +176,10 @@ static int ablerex_battery_charge(double BattIn) } static int ablerex_batterycharge(item_t *item, char *value, const size_t valuelen) { - double BattV = 0.0; + double BattV = 0.0; + double nomBattV = 0.0; + int BattP; + BattV = strtod(item->value, NULL); upsdebugx(2, "battvoltc2: %.2f", BattV); if (!dstate_getinfo("battery.voltage.nominal")) @@ -183,7 +188,6 @@ static int ablerex_batterycharge(item_t *item, char *value, const size_t valuele return 0; } - double nomBattV = 0.0; nomBattV = strtod(dstate_getinfo("battery.voltage.nominal"), NULL); upsdebugx(2, "battvv1: %.2f", nomBattV); //return 0; @@ -191,7 +195,7 @@ static int ablerex_batterycharge(item_t *item, char *value, const size_t valuele if (BattV > 3.0) { BattV = BattV / (nomBattV / 12); } - int BattP = ablerex_battery_charge(BattV); + BattP = ablerex_battery_charge(BattV); //dstate_setinfo("battery.charge", "%.0f", BattP); snprintf(value, valuelen, "%d", BattP); @@ -301,10 +305,12 @@ static int ablerex_process_status_bits(item_t *item, char *value, const size_t v status_set("RB"); } - double vout = strtod(dstate_getinfo("output.voltage"), NULL); + { /* scope */ + double vout = strtod(dstate_getinfo("output.voltage"), NULL); - if (vout < 50.0) { - status_set("OFF"); + if (vout < 50.0) { + status_set("OFF"); + } } break; diff --git a/drivers/nutdrv_qx_bestups.c b/drivers/nutdrv_qx_bestups.c index 30ed061458..7f1cd45b44 100644 --- a/drivers/nutdrv_qx_bestups.c +++ b/drivers/nutdrv_qx_bestups.c @@ -357,12 +357,14 @@ static int bestups_preprocess_id_answer(item_t *item, const int len) /* *SETVAR(/NONUT)* Preprocess setvars */ static int bestups_process_setvar(item_t *item, char *value, const size_t valuelen) { + double val; + if (!strlen(value)) { upsdebugx(2, "%s: value not given for %s", __func__, item->info_type); return -1; } - double val = strtod(value, NULL); + val = strtod(value, NULL); if (!strcasecmp(item->info_type, "pins_shutdown_mode")) { diff --git a/drivers/nutdrv_qx_masterguard.c b/drivers/nutdrv_qx_masterguard.c index e44b1ed382..85a0cae0f6 100644 --- a/drivers/nutdrv_qx_masterguard.c +++ b/drivers/nutdrv_qx_masterguard.c @@ -444,11 +444,11 @@ static int masterguard_fault(item_t *item, char *value, const size_t valuelen) { /* add slave address (from masterguard_my_slaveaddr) to commands that require it */ static int masterguard_add_slaveaddr(item_t *item, char *command, const size_t commandlen) { + size_t l; + NUT_UNUSED_VARIABLE(item); NUT_UNUSED_VARIABLE(commandlen); - size_t l; - l = strlen(command); if (strncmp(command + l - 4, ",XX\r", 4) != 0) { upsdebugx(1, "add slaveaddr: no ,XX\\r at end of command %s", command); @@ -465,13 +465,13 @@ static int masterguard_add_slaveaddr(item_t *item, char *command, const size_t c /* helper, not to be called directly from table */ /*!! use parameter from the value field instead of ups.delay.{shutdown,return}?? */ static int masterguard_shutdown(item_t *item, char *value, const size_t valuelen, const int stayoff) { - NUT_UNUSED_VARIABLE(item); - long offdelay; char *p; const char *val, *name; char offstr[3]; + NUT_UNUSED_VARIABLE(item); + offdelay = strtol((val = dstate_getinfo(name = "ups.delay.shutdown")), &p, 10); if (*p != '\0') goto ill; if (offdelay < 0) { @@ -511,15 +511,16 @@ static int masterguard_shutdown_stayoff(item_t *item, char *value, const size_t } static int masterguard_test_battery(item_t *item, char *value, const size_t valuelen) { - NUT_UNUSED_VARIABLE(item); - long duration; char *p; + NUT_UNUSED_VARIABLE(item); + if (value[0] == '\0') { upsdebugx(2, "battery test: no duration"); return -1; } + duration = strtol(value, &p, 10); if (*p != '\0') goto ill; if (duration == 10) { diff --git a/drivers/nutdrv_siemens_sitop.c b/drivers/nutdrv_siemens_sitop.c index ec84f4609d..1978f04022 100644 --- a/drivers/nutdrv_siemens_sitop.c +++ b/drivers/nutdrv_siemens_sitop.c @@ -98,7 +98,7 @@ static void rm_buffer_head(unsigned int n) { /* parse incoming data from the UPS. * return true if something new was received. */ -static int check_for_new_data() { +static int check_for_new_data(void) { int new_data_received = 0; int done = 0; ssize_t num_received; diff --git a/drivers/phoenixcontact_modbus.c b/drivers/phoenixcontact_modbus.c index 13aa8a0b41..733989ef68 100644 --- a/drivers/phoenixcontact_modbus.c +++ b/drivers/phoenixcontact_modbus.c @@ -57,12 +57,12 @@ void upsdrv_initinfo(void) void upsdrv_updateinfo(void) { + uint16_t tab_reg[64]; + errcount = 0; upsdebugx(2, "upsdrv_updateinfo"); - uint16_t tab_reg[64]; - mrir(modbus_ctx, 29697, 3, tab_reg); status_init(); diff --git a/drivers/pijuice.c b/drivers/pijuice.c index 2f589bcbfa..1d25376841 100644 --- a/drivers/pijuice.c +++ b/drivers/pijuice.c @@ -305,7 +305,7 @@ static inline int open_i2c_bus(char *path, uint8_t addr) return file; } -static void get_charge_level_hi_res() +static void get_charge_level_hi_res(void) { uint8_t cmd = CHARGE_LEVEL_HI_RES_CMD; uint16_t data; @@ -334,11 +334,10 @@ static void get_charge_level_hi_res() dstate_setinfo( "battery.charge", "%02.1f", battery_charge_level ); } -static void get_status() +static void get_status(void) { - uint8_t cmd = STATUS_CMD; - uint8_t data; - char status_buf[ST_MAX_VALUE_LEN]; + uint8_t cmd = STATUS_CMD, data, batteryStatus, powerInput, powerInput5vIo; + char status_buf[ST_MAX_VALUE_LEN]; upsdebugx( 3, __func__ ); @@ -346,7 +345,7 @@ static void get_status() I2C_READ_BYTE( upsfd, cmd, __func__ ) - uint8_t batteryStatus = data >> 2 & 0x03; + batteryStatus = data >> 2 & 0x03; switch( batteryStatus ) { case BATT_NORMAL: @@ -373,7 +372,7 @@ static void get_status() upsdebugx( 1, "battery.status: UNKNOWN" ); } - uint8_t powerInput = data >> 4 & 0x03; + powerInput = data >> 4 & 0x03; switch( powerInput ) { case POWER_NOT_PRESENT: @@ -392,7 +391,7 @@ static void get_status() upsdebugx( 1, "Power Input: UNKNOWN" ); } - uint8_t powerInput5vIo = data >> 6 & 0x03; + powerInput5vIo = data >> 6 & 0x03; switch( powerInput5vIo ) { case POWER_NOT_PRESENT : @@ -535,7 +534,7 @@ static void get_status() } } -static void get_battery_temperature() +static void get_battery_temperature(void) { uint8_t cmd = BATTERY_TEMPERATURE_CMD; int16_t data; @@ -548,7 +547,7 @@ static void get_battery_temperature() dstate_setinfo( "battery.temperature", "%d", data ); } -static void get_battery_voltage() +static void get_battery_voltage(void) { uint8_t cmd = BATTERY_VOLTAGE_CMD; int16_t data; @@ -561,7 +560,7 @@ static void get_battery_voltage() dstate_setinfo( "battery.voltage", "%0.3f", data / 1000.0 ); } -static void get_battery_current() +static void get_battery_current(void) { uint8_t cmd = BATTERY_CURRENT_CMD; int16_t data; @@ -583,7 +582,7 @@ static void get_battery_current() dstate_setinfo( "battery.current", "%0.3f", data / 1000.0 ); } -static void get_io_voltage() +static void get_io_voltage(void) { uint8_t cmd = IO_VOLTAGE_CMD; int16_t data; @@ -596,7 +595,7 @@ static void get_io_voltage() dstate_setinfo( "input.voltage", "%.3f", data / 1000.0 ); } -static void get_io_current() +static void get_io_current(void) { uint8_t cmd = IO_CURRENT_CMD; int16_t data; @@ -618,7 +617,7 @@ static void get_io_current() dstate_setinfo( "input.current", "%.3f", data / 1000.0 ); } -static void get_firmware_version() +static void get_firmware_version(void) { uint8_t cmd = FIRMWARE_VERSION_CMD; uint16_t data; @@ -640,7 +639,7 @@ static void get_firmware_version() dstate_setinfo( "ups.firmware", "%d.%d", major, minor ); } -static void get_battery_profile() +static void get_battery_profile(void) { uint8_t cmd = BATTERY_PROFILE_CMD; __u8 block[I2C_SMBUS_BLOCK_MAX]; @@ -653,7 +652,7 @@ static void get_battery_profile() dstate_setinfo( "battery.capacity", "%0.3f", ( block[1] << 8 | block[0] ) / 1000.0 ); } -static void get_battery_profile_ext() +static void get_battery_profile_ext(void) { uint8_t cmd = BATTERY_EXT_PROFILE_CMD; __u8 block[I2C_SMBUS_BLOCK_MAX]; @@ -678,7 +677,7 @@ static void get_battery_profile_ext() } } -static void get_power_off() +static void get_power_off(void) { uint8_t cmd = POWER_OFF_CMD; uint8_t data; @@ -697,7 +696,7 @@ static void get_power_off() } } -static void set_power_off() +static void set_power_off(void) { uint8_t cmd = POWER_OFF_CMD; @@ -729,7 +728,7 @@ static void set_power_off() I2C_WRITE_BYTE( upsfd, cmd, shutdown_delay, __func__ ) } -static void get_time() +static void get_time(void) { uint8_t cmd = RTC_TIME_CMD; __u8 block[I2C_SMBUS_BLOCK_MAX]; @@ -755,7 +754,7 @@ static void get_time() dstate_setinfo( "ups.date", "%04d-%02d-%02d", year, month, day ); } -static void get_i2c_address() +static void get_i2c_address(void) { uint8_t cmd = I2C_ADDRESS_CMD; uint8_t data; diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 15451a49db..053144654b 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -242,6 +242,9 @@ static void usb_comm_good(void) */ static int driver_callback(usb_dev_handle *handle, USBDevice_t *device) { +#if WITH_LIBUSB_1_0 + int ret = 0; +#endif NUT_UNUSED_VARIABLE(device); if (usb_set_configuration(handle, 1) < 0) { @@ -263,8 +266,6 @@ static int driver_callback(usb_dev_handle *handle, USBDevice_t *device) return -1; } #elif WITH_LIBUSB_1_0 - int ret = 0; - if ((ret = libusb_set_interface_alt_setting(handle, 0, 0)) < 0) { upsdebugx(5, "Can't set USB alternate interface: %s", nut_usb_strerror(ret)); return -1; @@ -307,6 +308,17 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev { int ret = 0; uint8_t iManufacturer = 0, iProduct = 0, iSerialNumber = 0; +#if WITH_LIBUSB_1_0 + libusb_device **devlist; + ssize_t devcount = 0; + libusb_device_handle *handle; + struct libusb_device_descriptor dev_desc; + uint8_t bus_num; + /* TODO: consider device_addr */ + int i; +#else /* => WITH_LIBUSB_0_1 */ + struct usb_bus *bus; +#endif /* libusb base init */ #if WITH_LIBUSB_1_0 @@ -328,14 +340,6 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #endif #if WITH_LIBUSB_1_0 - libusb_device **devlist; - ssize_t devcount = 0; - libusb_device_handle *handle; - struct libusb_device_descriptor dev_desc; - uint8_t bus_num; - /* TODO: consider device_addr */ - int i; - devcount = libusb_get_device_list(NULL, &devlist); if (devcount <= 0) fatal_with_errno(EXIT_FAILURE, "No USB device found"); @@ -348,8 +352,6 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev ret = libusb_open(dev, &handle); *handlep = handle; #else /* => WITH_LIBUSB_0_1 */ - struct usb_bus *bus; - for (bus = usb_busses; bus; bus = bus->next) { struct usb_device *dev; diff --git a/drivers/riello.c b/drivers/riello.c index fe1de5c905..0f4fc9d064 100644 --- a/drivers/riello.c +++ b/drivers/riello.c @@ -914,7 +914,7 @@ void riello_parse_sentr(uint8_t* buffer, TRielloData* data) data->StatusCode[2] |= 0x01; } -void riello_init_serial() +void riello_init_serial(void) { wait_packet = 1; buf_ptr_length = 0; diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index 2d5e85aa1f..810d9486de 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -207,7 +207,7 @@ static void riello_serialcomm(uint8_t* arg_bufIn, uint8_t typedev) } } -static int get_ups_nominal() +static int get_ups_nominal(void) { uint8_t length; @@ -240,7 +240,7 @@ static int get_ups_nominal() return 0; } -static int get_ups_status() +static int get_ups_status(void) { uint8_t numread, length; @@ -280,7 +280,7 @@ static int get_ups_status() return 0; } -static int get_ups_extended() +static int get_ups_extended(void) { uint8_t length; @@ -314,7 +314,7 @@ static int get_ups_extended() } /* Not static, exposed via header. Not used though, currently... */ -int get_ups_statuscode() +int get_ups_statuscode(void) { uint8_t length; @@ -347,7 +347,7 @@ int get_ups_statuscode() return 0; } -static int get_ups_sentr() +static int get_ups_sentr(void) { uint8_t length; @@ -679,7 +679,7 @@ static int riello_instcmd(const char *cmdname, const char *extra) return STAT_INSTCMD_UNKNOWN; } -static int start_ups_comm() +static int start_ups_comm(void) { uint8_t length; diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 1a7fe7d4f3..23f326c324 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -81,7 +81,7 @@ static void ussleep(useconds_t usec) usleep(usec); } -static int cypress_setfeatures() +static int cypress_setfeatures(void) { int ret; @@ -434,7 +434,7 @@ static int riello_command(uint8_t *cmd, uint8_t *buf, uint16_t length, uint16_t return ret; } -static int get_ups_nominal() +static int get_ups_nominal(void) { uint8_t length; @@ -467,7 +467,7 @@ static int get_ups_nominal() return 0; } -static int get_ups_status() +static int get_ups_status(void) { uint8_t numread, length; int recv; @@ -506,7 +506,7 @@ static int get_ups_status() return 0; } -static int get_ups_extended() +static int get_ups_extended(void) { uint8_t length; int recv; @@ -539,7 +539,7 @@ static int get_ups_extended() } /* Not static, exposed via header. Not used though, currently... */ -int get_ups_statuscode() +int get_ups_statuscode(void) { uint8_t length; int recv; @@ -795,7 +795,7 @@ static int riello_instcmd(const char *cmdname, const char *extra) return STAT_INSTCMD_UNKNOWN; } -static int start_ups_comm() +static int start_ups_comm(void) { uint16_t length; int recv; diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index fa108c9b37..ba9f5438e2 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -593,10 +593,11 @@ void upsdrv_initups(void) /* Retrieve user's parameters */ mibs = testvar(SU_VAR_MIBS) ? getval(SU_VAR_MIBS) : "auto"; 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); - int i; printf("%7s\t%-23s\t%-7s\t%-31s\t%-s\n", "NUMBER", "MAPPING NAME", "VERSION", "ENTRY POINT OID", "AUTO CHECK OID"); @@ -1122,6 +1123,8 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) current_name_len = name_len; while( nb_iteration < max_iteration ) { + struct snmp_pdu **new_ret_array; + /* Going to a shorter OID means we are outside our sub-tree */ if( current_name_len < name_len ) { break; @@ -1204,7 +1207,7 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) nb_iteration++; /* +1 is for the terminating NULL */ - struct snmp_pdu ** new_ret_array = realloc( + new_ret_array = realloc( ret_array, sizeof(struct snmp_pdu*) * ((size_t)nb_iteration+1) ); @@ -1261,21 +1264,24 @@ static bool_t decode_str(struct snmp_pdu *pdu, char *buf, size_t buf_len, info_l switch (pdu->variables->type) { case ASN_OCTET_STR: case ASN_OPAQUE: - len = pdu->variables->val_len > buf_len - 1 ? - buf_len - 1 : pdu->variables->val_len; - /* Test for hexadecimal values */ - int hex = 0, x; - unsigned char *cp; - for(cp = pdu->variables->val.string, x = 0; x < (int)pdu->variables->val_len; x++, cp++) { - if (!(isprint((size_t)*cp) || isspace((size_t)*cp))) { - hex = 1; + { /* scoping */ + /* Test for hexadecimal values */ + int hex = 0, x; + unsigned char *cp; + + len = pdu->variables->val_len > buf_len - 1 ? + buf_len - 1 : pdu->variables->val_len; + for(cp = pdu->variables->val.string, x = 0; x < (int)pdu->variables->val_len; x++, cp++) { + if (!(isprint((size_t)*cp) || isspace((size_t)*cp))) { + hex = 1; + } + } + if (hex) + snprint_hexstring(buf, buf_len, pdu->variables->val.string, pdu->variables->val_len); + else { + memcpy(buf, pdu->variables->val.string, len); + buf[len] = '\0'; } - } - if (hex) - snprint_hexstring(buf, buf_len, pdu->variables->val.string, pdu->variables->val_len); - else { - memcpy(buf, pdu->variables->val.string, len); - buf[len] = '\0'; } break; case ASN_INTEGER: @@ -1320,9 +1326,10 @@ static bool_t decode_str(struct snmp_pdu *pdu, char *buf, size_t buf_len, info_l upsdebugx(2, "Received an OID value: %s", tmp_buf); /* Try to get the value of the pointed OID */ if (nut_snmp_get_str(tmp_buf, buf, buf_len, oid2info) == FALSE) { + char *oid_leaf; upsdebugx(3, "Failed to retrieve OID value, using fallback"); /* Otherwise return the last part of the returned OID (ex: 1.2.3 => 3) */ - char *oid_leaf = strrchr(tmp_buf, '.'); + oid_leaf = strrchr(tmp_buf, '.'); snprintf(buf, buf_len, "%s", oid_leaf+1); upsdebugx(3, "Fallback value: %s", buf); } @@ -1441,9 +1448,10 @@ bool_t nut_snmp_get_int(const char *OID, long *pval) upsdebugx(2, "Received an OID value: %s", tmp_buf); /* Try to get the value of the pointed OID */ if (nut_snmp_get_int(tmp_buf, &value) == FALSE) { + char *oid_leaf; upsdebugx(3, "Failed to retrieve OID value, using fallback"); /* Otherwise return the last part of the returned OID (ex: 1.2.3 => 3) */ - char *oid_leaf = strrchr(tmp_buf, '.'); + oid_leaf = strrchr(tmp_buf, '.'); value = strtol(oid_leaf+1, NULL, 0); upsdebugx(3, "Fallback value: %ld", value); } @@ -1795,9 +1803,10 @@ void su_alarm_set(snmp_info_t *su_info_p, long value) * start of path */ if (info_type[0] == 'L') { /* Extract phase number */ - item_number = atoi(info_type+1); char alarm_info_value_more[SU_LARGEBUF + 32]; /* can sprintf() SU_LARGEBUF plus markup into here */ + item_number = atoi(info_type+1); + upsdebugx(2, "%s: appending phase L%i", __func__, item_number); /* Inject in the alarm string */ @@ -1837,7 +1846,7 @@ snmp_info_t *su_find_info(const char *type) /* Counter match the sysOID using {device,ups}.model OID * Return TRUE if this OID can be retrieved, FALSE otherwise */ -static bool_t match_model_OID() +static bool_t match_model_OID(void) { bool_t retCode = FALSE; snmp_info_t *su_info_p, *cur_info_p; @@ -1899,7 +1908,7 @@ static bool_t match_model_OID() /* Try to find the MIB using sysOID matching. * Return a pointer to a mib2nut definition if found, NULL otherwise */ -static mib2nut_info_t *match_sysoid() +static mib2nut_info_t *match_sysoid(void) { char sysOID_buf[LARGEBUF]; oid device_sysOID[MAX_OID_LEN]; @@ -2147,14 +2156,16 @@ long su_find_valinfo(info_lkp_t *oid2info, const char* value) return -1; } -/* String reformating function */ +/* String reformatting function */ const char *su_find_strval(info_lkp_t *oid2info, void *value) { #if WITH_SNMP_LKP_FUN /* First test if we have a generic lookup function */ if ( (oid2info != NULL) && (oid2info->fun_vp2s != NULL) ) { + const char *retvalue; + upsdebugx(2, "%s: using generic lookup function (string reformatting)", __func__); - const char * retvalue = oid2info->fun_vp2s(value); + retvalue = oid2info->fun_vp2s(value); upsdebugx(2, "%s: got value '%s'", __func__, retvalue); return retvalue; } @@ -2175,8 +2186,10 @@ const char *su_find_infoval(info_lkp_t *oid2info, void *raw_value) #if WITH_SNMP_LKP_FUN /* First test if we have a generic lookup function */ if ( (oid2info != NULL) && (oid2info->fun_vp2s != NULL) ) { + const char *retvalue; + upsdebugx(2, "%s: using generic lookup function", __func__); - const char * retvalue = oid2info->fun_vp2s(raw_value); + retvalue = oid2info->fun_vp2s(raw_value); upsdebugx(2, "%s: got value '%s'", __func__, retvalue); return retvalue; } @@ -2338,12 +2351,14 @@ static void free_info(snmp_info_t *su_info_p) * the MIB, based on a test using a template OID */ static int base_snmp_template_index(const snmp_info_t *su_info_p) { + int base_index = -1; + char test_OID[SU_INFOSIZE]; + snmp_info_flags_t template_type; + if (!su_info_p) return -1; - int base_index = -1; - char test_OID[SU_INFOSIZE]; - snmp_info_flags_t template_type = get_template_type(su_info_p->info_type); + template_type = get_template_type(su_info_p->info_type); upsdebugx(3, "%s: OID template = %s", __func__, (su_info_p->OID ? su_info_p->OID : "") ); @@ -2863,7 +2878,7 @@ bool_t get_and_process_data(int mode, snmp_info_t *su_info_p) * Determine the number of device(s) and if daisychain support has to be enabled * Set the values of devices_count (internal) and "device.count" (public) * Return TRUE if daisychain support is enabled, FALSE otherwise */ -bool_t daisychain_init() +bool_t daisychain_init(void) { snmp_info_t *su_info_p = NULL; @@ -3132,7 +3147,10 @@ static int process_phase_data(const char* type, long *nb_phases, snmp_info_t *su bool_t snmp_ups_walk(int mode) { long *walked_input_phases, *walked_output_phases, *walked_bypass_phases; - static unsigned long iterations = 0; +#ifdef COUNT_ITERATIONS + /* Experimental workaround for stale info */ + static unsigned long iterations = 0; +#endif snmp_info_t *su_info_p; bool_t status = FALSE; @@ -3291,11 +3309,13 @@ bool_t snmp_ups_walk(int mode) continue; } +#ifdef COUNT_ITERATIONS /* check stale elements only on each PN_STALE_RETRY iteration. */ - /* if ((su_info_p->flags & SU_FLAG_STALE) && + if ((su_info_p->flags & SU_FLAG_STALE) && (iterations % SU_STALE_RETRY) != 0) continue; - */ +#endif + /* Filter 1-phase Vs 3-phase according to {input,output,bypass}.phase. * Non matching items are disabled, and flags are cleared at init * time */ @@ -3366,7 +3386,11 @@ bool_t snmp_ups_walk(int mode) device_alarm_init(); } } + +#ifdef COUNT_ITERATIONS iterations++; +#endif + return status; } @@ -3640,6 +3664,7 @@ bool_t su_ups_get(snmp_info_t *su_info_p) status = nut_snmp_get_str(su_info_p->OID, buf, sizeof(buf), su_info_p->oid2info); if (status == TRUE) { + const char *fmt_buf; if (quirk_symmetra_threephase) { if (!strcasecmp(su_info_p->info_type, "input.transfer.low") || !strcasecmp(su_info_p->info_type, "input.transfer.high")) { @@ -3649,8 +3674,8 @@ bool_t su_ups_get(snmp_info_t *su_info_p) snprintf(buf, sizeof(buf), "%.2f", tmp_dvalue); } } - /* Check if there is a string reformating function */ - const char *fmt_buf = NULL; + /* Check if there is a string reformatting function */ + fmt_buf = NULL; if ((fmt_buf = su_find_strval(su_info_p->oid2info, buf)) != NULL) { snprintf(buf, sizeof(buf), "%s", fmt_buf); } @@ -3724,7 +3749,7 @@ static int su_setOID(int mode, const char *varname, const char *val) snmp_info_t *su_info_p = NULL; bool_t status; int retval = STAT_SET_FAILED; - int cmd_offset = 0; + int cmd_offset = 0; /* FIXME: Does not seem to be actually used! */ long value = -1; /* normal (default), outlet, or outlet group variable */ snmp_info_flags_t vartype = 0; @@ -3846,13 +3871,14 @@ static int su_setOID(int mode, const char *varname, const char *val) } } else { /* is indeed an outlet.* or device.x.outlet.* */ - snmp_info_t *tmp_info_p; + snmp_info_t *tmp_info_p; /* Point the outlet or outlet group number in the string */ - const char *item_number_ptr = NULL; + const char *item_number_ptr = NULL; + char *item_varname; /* Store the target outlet or group number */ - int item_number = extract_template_number_from_snmp_info_t(tmp_varname); + int item_number = extract_template_number_from_snmp_info_t(tmp_varname); /* Store the total number of outlets or outlet groups */ - int total_items = -1; + int total_items = -1; /* Check if it is outlet / outlet.group */ vartype = get_template_type(tmp_varname); @@ -3878,7 +3904,7 @@ static int su_setOID(int mode, const char *varname, const char *val) return STAT_SET_INVALID; } /* find back the item template */ - char *item_varname = (char *)xmalloc(SU_INFOSIZE); + item_varname = (char *)xmalloc(SU_INFOSIZE); snprintf(item_varname, SU_INFOSIZE, "%s.%s%s", (vartype == SU_OUTLET)?"outlet":"outlet.group", "%i", strchr(item_number_ptr++, '.')); @@ -3916,8 +3942,8 @@ static int su_setOID(int mode, const char *varname, const char *val) /* Workaround buggy Eaton Pulizzi implementation * which have different offsets index for data & commands! */ if (su_info_p->flags & SU_CMD_OFFSET) { - upsdebugx(3, "Adding command offset"); cmd_offset++; + upsdebugx(3, "Adding command offset, now: %i", cmd_offset); } } diff --git a/drivers/socomec_jbus.c b/drivers/socomec_jbus.c index 84d585d39b..dc9e260ce0 100644 --- a/drivers/socomec_jbus.c +++ b/drivers/socomec_jbus.c @@ -53,11 +53,11 @@ upsdrv_info_t upsdrv_info = { void upsdrv_initinfo(void) { - upsdebugx(2, "upsdrv_initinfo"); - uint16_t tab_reg[12]; int r; + upsdebugx(2, "upsdrv_initinfo"); + dstate_setinfo("device.mfr", "socomec jbus"); dstate_setinfo("device.model", "Socomec Generic"); @@ -117,11 +117,11 @@ void upsdrv_initinfo(void) void upsdrv_updateinfo(void) { - upsdebugx(2, "upsdrv_updateinfo"); - uint16_t tab_reg[64]; int r; + upsdebugx(2, "upsdrv_updateinfo"); + status_init(); /* ups configuration */ diff --git a/drivers/solis.c b/drivers/solis.c index eb1cee47d0..ee0f0a456c 100644 --- a/drivers/solis.c +++ b/drivers/solis.c @@ -413,16 +413,18 @@ static void scan_received_pack(void) { OutVoltage = RecPack[1] * a * TENSAO_SAIDA_F1_MI[configRelay] + TENSAO_SAIDA_F2_MI[configRelay]; } } else { + double RealPower, potVA1, potVA2, potLin, potRe; + OutCurrent = (float)(corrente_saida_F1_MR * RecPack[5] + corrente_saida_F2_MR); OutVoltage = RecPack[1] * TENSAO_SAIDA_F1_MR[configRelay] + TENSAO_SAIDA_F2_MR[configRelay]; AppPower = OutCurrent * OutVoltage; - double RealPower = (RecPack[7] + RecPack[8] * 256); + RealPower = (RecPack[7] + RecPack[8] * 256); - double potVA1 = 5.968 * AppPower - 284.36; - double potVA2 = 7.149 * AppPower - 567.18; - double potLin = 0.1664 * RealPower + 49.182; - double potRe = 0.1519 * RealPower + 32.644; + potVA1 = 5.968 * AppPower - 284.36; + potVA2 = 7.149 * AppPower - 567.18; + potLin = 0.1664 * RealPower + 49.182; + potRe = 0.1519 * RealPower + 32.644; if (fabs(potVA1 - RealPower) < fabs(potVA2 - RealPower)) RealPower = potLin; else diff --git a/drivers/tripplite.c b/drivers/tripplite.c index 76ec0b0a8a..f353c38a7e 100644 --- a/drivers/tripplite.c +++ b/drivers/tripplite.c @@ -612,9 +612,10 @@ void upsdrv_makevartable(void) void upsdrv_initups(void) { + char *val; + upsfd = ser_open(device_path); ser_set_speed(upsfd, device_path, B2400); - char *val; if ((val = getval("offdelay"))) { int ipv = atoi(val); diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 858b93dcd0..505f69fc9d 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -173,19 +173,19 @@ static int subdriver_match_func(USBDevice_t *arghd, void *privdata) switch (is_usb_device_supported(tripplite_usb_device_table, arghd)) { - case SUPPORTED: - return 1; - - case POSSIBLY_SUPPORTED: - /* by default, reject, unless the productid option is given */ - if (getval("productid")) { + case SUPPORTED: return 1; - } - return 0; - case NOT_SUPPORTED: - default: - return 0; + case POSSIBLY_SUPPORTED: + /* by default, reject, unless the productid option is given */ + if (getval("productid")) { + return 1; + } + return 0; + + case NOT_SUPPORTED: + default: + return 0; } } @@ -207,58 +207,58 @@ static enum tl_model_t { /*! Are the values encoded in ASCII or binary? * TODO: Add 3004? */ -static int is_binary_protocol() +static int is_binary_protocol(void) { switch(tl_model) { - case TRIPP_LITE_SMART_3005: - return 1; - case TRIPP_LITE_SMARTPRO: - case TRIPP_LITE_SMART_0004: - case TRIPP_LITE_OMNIVS: - case TRIPP_LITE_OMNIVS_2001: - case TRIPP_LITE_UNKNOWN: + case TRIPP_LITE_SMART_3005: + return 1; + case TRIPP_LITE_SMARTPRO: + case TRIPP_LITE_SMART_0004: + case TRIPP_LITE_OMNIVS: + case TRIPP_LITE_OMNIVS_2001: + case TRIPP_LITE_UNKNOWN: #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcovered-switch-default" #endif - /* All enum cases defined as of the time of coding - * have been covered above. Handle later definitions, - * memory corruptions and buggy inputs below... - */ - default: + /* All enum cases defined as of the time of coding + * have been covered above. Handle later definitions, + * memory corruptions and buggy inputs below... + */ + default: #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) # pragma GCC diagnostic pop #endif - return 0; + return 0; } } /*! Is this the "SMART" family of protocols? * TODO: Add 3004? */ -static int is_smart_protocol() +static int is_smart_protocol(void) { switch(tl_model) { - case TRIPP_LITE_SMARTPRO: - case TRIPP_LITE_SMART_0004: - case TRIPP_LITE_SMART_3005: - return 1; - case TRIPP_LITE_OMNIVS: - case TRIPP_LITE_OMNIVS_2001: - case TRIPP_LITE_UNKNOWN: + case TRIPP_LITE_SMARTPRO: + case TRIPP_LITE_SMART_0004: + case TRIPP_LITE_SMART_3005: + return 1; + case TRIPP_LITE_OMNIVS: + case TRIPP_LITE_OMNIVS_2001: + case TRIPP_LITE_UNKNOWN: #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcovered-switch-default" #endif - /* All enum cases defined as of the time of coding - * have been covered above. Handle later definitions, - * memory corruptions and buggy inputs below... - */ - default: + /* All enum cases defined as of the time of coding + * have been covered above. Handle later definitions, + * memory corruptions and buggy inputs below... + */ + default: #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) # pragma GCC diagnostic pop #endif - return 0; + return 0; } } @@ -595,11 +595,11 @@ static void usb_comm_fail(int res, const char *msg) */ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *reply, size_t reply_len) { - NUT_UNUSED_VARIABLE(reply_len); unsigned char buffer_out[8]; unsigned char csum = 0; int ret = 0, send_try, recv_try=0, done = 0; size_t i = 0; + NUT_UNUSED_VARIABLE(reply_len); upsdebugx(3, "send_cmd(msg_len=%u, type='%c')", (unsigned)msg_len, msg[0]); diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index a5e5d05da0..1d8461903a 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -252,6 +252,7 @@ static ssize_t do_command(char type, const char *command, const char *parameters upsdebugx(3, "do_command: %" PRIiSIZE " byted read [%s]", ret, buffer); if (!strcmp(buffer, "~00D")) { + int c; ret = ser_get_buf_len(upsfd, (unsigned char *)buffer, 3, 3, 0); if (ret < 0) { @@ -266,7 +267,7 @@ static ssize_t do_command(char type, const char *command, const char *parameters buffer[ret] = '\0'; upsdebugx(3, "do_command: %" PRIiSIZE " bytes read [%s]", ret, buffer); - int c = atoi(buffer); + c = atoi(buffer); if (c < 0) { upsdebugx(3, "do_command: response not expected to be a negative count!"); return -1; diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 3c07ceb4c1..ae42de32b2 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -527,13 +527,15 @@ static void set_reload_flag(const static void setup_signals(void) { +#ifndef WIN32 + struct sigaction sa; +#endif + set_exit_flag(0); reset_signal_flag(); #ifndef WIN32 /* Keep in sync with signal handling in drivers/main.c */ - struct sigaction sa; - sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = set_exit_flag; diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 86f9a04c58..3f273e5d19 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -187,6 +187,13 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { ssize_t ret; +#ifndef WIN32 + fd_set rfds; +#else + DWORD bytesRead = 0; + BOOL res = FALSE; + struct timeval start, now, presleep; +#endif if (!conn || INVALID_FD(conn->sockfd)) { upslog_with_errno(LOG_ERR, "socket not initialized"); @@ -194,8 +201,6 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { } #ifndef WIN32 - fd_set rfds; - FD_ZERO(&rfds); FD_SET(conn->sockfd, &rfds); @@ -217,9 +222,6 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { upslog_with_errno(LOG_ERR, "Support for this platform is not currently implemented"); return -1; */ - DWORD bytesRead = 0; - BOOL res = FALSE; - struct timeval start, now, presleep; /* Is GetLastError() required to move on if pipe has more data? * if (GetLastError() == ERROR_IO_PENDING) { @@ -321,6 +323,12 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { size_t buflen = strlen(buf); +#ifndef WIN32 + int ret; +#else + DWORD bytesWritten = 0; + BOOL result = FALSE; +#endif /* WIN32 */ upsdebugx(5, "%s: write to driver socket: %s", __func__, buf); @@ -330,7 +338,7 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { } #ifndef WIN32 - int ret = write(conn->sockfd, buf, buflen); + ret = write(conn->sockfd, buf, buflen); if (ret < 0 || ret != (int)buflen) { upslog_with_errno(LOG_ERR, "Write to socket %d failed", conn->sockfd); @@ -339,9 +347,6 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { return ret; #else - DWORD bytesWritten = 0; - BOOL result = FALSE; - result = WriteFile(conn->sockfd, buf, buflen, &bytesWritten, NULL); if (result == 0 || bytesWritten != (DWORD)buflen) { upslog_with_errno(LOG_ERR, "Write to handle %p failed", conn->sockfd); diff --git a/server/netssl.c b/server/netssl.c index 1a593c7a1a..7557f26624 100644 --- a/server/netssl.c +++ b/server/netssl.c @@ -639,6 +639,9 @@ void ssl_init(void) ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen) { ssize_t ret = -1; +#ifdef WITH_OPENSSL + int iret; +#endif if (!client->ssl_connected) { return -1; @@ -651,7 +654,7 @@ ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen) * but smaller systems with 16-bits might be endangered :) */ assert(buflen <= INT_MAX); - int iret = SSL_read(client->ssl, buf, (int)buflen); + iret = SSL_read(client->ssl, buf, (int)buflen); assert(iret <= SSIZE_MAX); ret = (ssize_t)iret; #elif defined(WITH_NSS) /* WITH_OPENSSL */ @@ -672,6 +675,9 @@ ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen) ssize_t ssl_write(nut_ctype_t *client, const char *buf, size_t buflen) { ssize_t ret = -1; +#ifdef WITH_OPENSSL + int iret; +#endif if (!client->ssl_connected) { return -1; @@ -684,7 +690,7 @@ ssize_t ssl_write(nut_ctype_t *client, const char *buf, size_t buflen) * but smaller systems with 16-bits might be endangered :) */ assert(buflen <= INT_MAX); - int iret = SSL_write(client->ssl, buf, (int)buflen); + iret = SSL_write(client->ssl, buf, (int)buflen); assert(iret <= SSIZE_MAX); ret = (ssize_t)iret; #elif defined(WITH_NSS) /* WITH_OPENSSL */ diff --git a/server/upsd.c b/server/upsd.c index 7123d625d6..5e4b37e7dd 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -995,6 +995,7 @@ static void poll_reload(void) { #ifndef WIN32 long ret; + size_t maxalloc; ret = sysconf(_SC_OPEN_MAX); @@ -1012,7 +1013,7 @@ static void poll_reload(void) } /* How many items can we stuff into the array? */ - size_t maxalloc = SIZE_MAX / sizeof(void *); + maxalloc = SIZE_MAX / sizeof(void *); 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" diff --git a/tests/getvaluetest.c b/tests/getvaluetest.c index fdaffc1cae..76a6a96d33 100644 --- a/tests/getvaluetest.c +++ b/tests/getvaluetest.c @@ -65,8 +65,6 @@ static void PrintBufAndData(uint8_t *buf, size_t bufSize, HIDData_t *pData) { } static int RunBuiltInTests(char *argv[]) { - NUT_UNUSED_VARIABLE(argv); - int exitStatus = 0; size_t i; char *next; @@ -104,6 +102,14 @@ static int RunBuiltInTests(char *argv[]) { {.buf = "16 0c 00 00 00", .Offset = 10, .Size = 1, .LogMin = 0, .LogMax = 1, .expectedValue = 0} }; + /* See comments below about rdlen calculation emulation for tests */ + usb_ctrl_char bufC[2]; + signed char bufS[2]; + unsigned char bufU[2]; + int rdlen; + + NUT_UNUSED_VARIABLE(argv); + for (i = 0; i < sizeof(testData)/sizeof(testData[0]); i++) { next = testData[i].buf; for (bufSize = 0; *next != 0; bufSize++) { @@ -134,10 +140,6 @@ static int RunBuiltInTests(char *argv[]) { * from the protocol buffer, and build a platform * dependent representation of a two-byte word. */ - usb_ctrl_char bufC[2]; - signed char bufS[2]; - unsigned char bufU[2]; - int rdlen; /* Example from issue https://github.com/networkupstools/nut/issues/1261 * where resulting length 0x01a9 should be "425" but ended up "-87" */ diff --git a/tests/nuttimetest.c b/tests/nuttimetest.c index 49e2264298..2ef2444d11 100644 --- a/tests/nuttimetest.c +++ b/tests/nuttimetest.c @@ -28,7 +28,7 @@ #include #include -static int check_difftime() +static int check_difftime(void) { time_t tv1, tv2; double d1, d2; @@ -64,7 +64,7 @@ static int check_difftime() return res; } -static int check_difftimeval() +static int check_difftimeval(void) { struct timeval tv1, tv2; double d1, d2; @@ -101,7 +101,7 @@ static int check_difftimeval() return res; } -static int check_difftimespec() +static int check_difftimespec(void) { int res = 0; #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) && HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 8a20f1a38e..aed5624792 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -173,7 +173,7 @@ static void * run_eaton_serial(void *arg) #endif /* HAVE_PTHREAD */ -static void show_usage() +static void show_usage(void) { /* NOTE: This code uses `nutscan_avail_*` global vars from nutscan-init.c */ puts("nut-scanner : utility for detection of available power devices.\n"); @@ -362,6 +362,11 @@ int main(int argc, char *argv[]) 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); int ret_code = EXIT_SUCCESS; +#ifdef HAVE_PTHREAD +# ifdef HAVE_SEMAPHORE + sem_t *current_sem; +# endif +#endif #if (defined HAVE_PTHREAD) && ( (defined HAVE_PTHREAD_TRYJOIN) || (defined HAVE_SEMAPHORE) ) && (defined HAVE_SYS_RESOURCE_H) struct rlimit nofile_limit; @@ -694,7 +699,7 @@ int main(int argc, char *argv[]) /* 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). */ - sem_t *current_sem = nutscan_semaphore(); + current_sem = nutscan_semaphore(); sem_destroy(current_sem); #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE #pragma GCC diagnostic push diff --git a/tools/nut-scanner/nutscan-device.c b/tools/nut-scanner/nutscan-device.c index bde57fed71..d22e23f027 100644 --- a/tools/nut-scanner/nutscan-device.c +++ b/tools/nut-scanner/nutscan-device.c @@ -37,7 +37,7 @@ const char * nutscan_device_type_strings[TYPE_END - 1] = { "serial", }; -nutscan_device_t * nutscan_new_device() +nutscan_device_t * nutscan_new_device(void) { nutscan_device_t * device; diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index f7e0efeacc..f3829b95c1 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -108,6 +108,8 @@ void do_upsconf_args(char *confupsname, char *var, char *val) { void nutscan_init(void) { + char *libname = NULL; + #ifdef HAVE_PTHREAD /* TOTHINK: Should semaphores to limit thread count * and the more naive but portable methods be an @@ -149,8 +151,6 @@ void nutscan_init(void) # endif #endif /* HAVE_PTHREAD */ - char *libname = NULL; - #ifdef WITH_USB #if WITH_LIBUSB_1_0 libname = get_libname("libusb-1.0" SOEXT); diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 9537c520c5..4fc410d2fc 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -322,9 +322,10 @@ int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) /* Detecting IPv4 vs IPv6 */ if (getaddrinfo(first_ip, NULL, &hints, &res) != 0) { /*Try IPv6 detection */ + int ret; + ip.type = IPv6; hints.ai_family = AF_INET6; - int ret; if ((ret = getaddrinfo(first_ip, NULL, &hints, &res)) != 0) { free(first_ip); return 0; diff --git a/tools/nut-scanner/scan_eaton_serial.c b/tools/nut-scanner/scan_eaton_serial.c index 93476a4a19..205f3ad109 100644 --- a/tools/nut-scanner/scan_eaton_serial.c +++ b/tools/nut-scanner/scan_eaton_serial.c @@ -539,13 +539,14 @@ nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) #ifdef HAVE_PTHREAD if (pthread_create(&thread, NULL, nutscan_scan_eaton_serial_device, (void*)current_port_name) == 0) { + nutscan_thread_t *new_thread_array; # ifdef HAVE_PTHREAD_TRYJOIN pthread_mutex_lock(&threadcount_mutex); curr_threads++; # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - nutscan_thread_t *new_thread_array = realloc(thread_array, + new_thread_array = 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 7b2e5f1a1a..f8e75c572c 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -440,13 +440,14 @@ nutscan_device_t * nutscan_scan_nut(const char* startIP, const char* stopIP, con #ifdef HAVE_PTHREAD if (pthread_create(&thread, NULL, list_nut_devices, (void*)nut_arg) == 0) { + nutscan_thread_t *new_thread_array; # ifdef HAVE_PTHREAD_TRYJOIN pthread_mutex_lock(&threadcount_mutex); curr_threads++; # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - nutscan_thread_t *new_thread_array = realloc(thread_array, + new_thread_array = 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 7e3568bd8c..8a28b8e9b1 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -567,6 +567,7 @@ static struct snmp_pdu * scan_snmp_get_oid(char* oid_str, void* handle) return NULL; } + upsdebugx(3, "%s: collected index: %i", __func__, index); return response; } @@ -1004,6 +1005,7 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip useconds_t usec_timeout, nutscan_snmp_t * sec) { bool_t pass = TRUE; /* Track that we may spawn a scanning thread */ + nutscan_device_t * result; nutscan_snmp_t * tmp_sec; nutscan_ip_iter_t ip; char * ip_str = NULL; @@ -1166,13 +1168,14 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip #ifdef HAVE_PTHREAD if (pthread_create(&thread, NULL, try_SysOID, (void*)tmp_sec) == 0) { + nutscan_thread_t *new_thread_array; # ifdef HAVE_PTHREAD_TRYJOIN pthread_mutex_lock(&threadcount_mutex); curr_threads++; # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - nutscan_thread_t *new_thread_array = realloc(thread_array, + new_thread_array = realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); @@ -1281,7 +1284,7 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip # endif /* HAVE_SEMAPHORE */ #endif /* HAVE_PTHREAD */ - nutscan_device_t * result = nutscan_rewind_device(dev_ret); + result = nutscan_rewind_device(dev_ret); dev_ret = NULL; return result; } diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index a56c54cf8a..0e355f86b7 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -246,7 +246,7 @@ static char* is_usb_device_supported(usb_device_id_t *usb_device_id_list, } /* return NULL if error */ -nutscan_device_t * nutscan_scan_usb() +nutscan_device_t * nutscan_scan_usb(void) { int ret; char string[256]; @@ -289,6 +289,9 @@ nutscan_device_t * nutscan_scan_usb() * available in libusb (and hoping the OS and HW honour it). */ char *bus_port = NULL; + ssize_t devcount = 0; + struct libusb_device_descriptor dev_desc; + int i; #else /* => WITH_LIBUSB_0_1 */ struct usb_device *dev; struct usb_bus *bus; @@ -316,10 +319,6 @@ nutscan_device_t * nutscan_scan_usb() #endif /* WITH_LIBUSB_1_0 */ #if WITH_LIBUSB_1_0 - ssize_t devcount = 0; - struct libusb_device_descriptor dev_desc; - int i; - devcount = (*nut_usb_get_device_list)(NULL, &devlist); if (devcount <= 0) { (*nut_usb_exit)(NULL); @@ -624,7 +623,7 @@ nutscan_device_t * nutscan_scan_usb() #else /* not WITH_USB */ /* stub function */ -nutscan_device_t * nutscan_scan_usb() +nutscan_device_t * nutscan_scan_usb(void) { return NULL; } diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 80c59b5008..b9ebcdb907 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -189,7 +189,6 @@ static void * nutscan_scan_xml_http_generic(void * arg) int sockopt_on = 1; struct sockaddr_in sockAddress_udp; socklen_t sockAddressLength = sizeof(sockAddress_udp); - memset(&sockAddress_udp, 0, sizeof(sockAddress_udp)); fd_set fds; struct timeval timeout; int ret; @@ -197,14 +196,18 @@ static void * nutscan_scan_xml_http_generic(void * arg) char string[SMALLBUF]; ssize_t recv_size; int i; - + nutscan_device_t * nut_dev = NULL; #ifdef WIN32 WSADATA WSAdata; +#endif + + memset(&sockAddress_udp, 0, sizeof(sockAddress_udp)); + +#ifdef WIN32 WSAStartup(2,&WSAdata); atexit((void(*)(void))WSACleanup); #endif - nutscan_device_t * nut_dev = NULL; if (sec != NULL) { /* if (sec->port_http > 0 && sec->port_http <= 65534) * port_http = sec->port_http; */ @@ -277,6 +280,9 @@ static void * nutscan_scan_xml_http_generic(void * arg) while ((ret = select(peerSocket + 1, &fds, NULL, NULL, &timeout)) ) { + ne_xml_parser *parser; + int parserFailed; + retNum ++; upsdebugx(5, "nutscan_scan_xml_http_generic() : request to %s, " "loop #%d/%d, response #%d", @@ -334,12 +340,12 @@ static void * nutscan_scan_xml_http_generic(void * arg) string, port_udp); nut_dev->type = TYPE_XML; /* Try to read device type */ - ne_xml_parser *parser = (*nut_ne_xml_create)(); + parser = (*nut_ne_xml_create)(); (*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); - int parserFailed = (*nut_ne_xml_failed)(parser); /* 0 = ok, nonzero = fail */ + parserFailed = (*nut_ne_xml_failed)(parser); /* 0 = ok, nonzero = fail */ (*nut_ne_xml_destroy)(parser); if (parserFailed == 0) { @@ -574,13 +580,14 @@ nutscan_device_t * nutscan_scan_xml_http_range(const char * start_ip, const char #ifdef HAVE_PTHREAD if (pthread_create(&thread, NULL, nutscan_scan_xml_http_generic, (void *)tmp_sec) == 0) { + nutscan_thread_t *new_thread_array; # ifdef HAVE_PTHREAD_TRYJOIN pthread_mutex_lock(&threadcount_mutex); curr_threads++; # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - nutscan_thread_t *new_thread_array = realloc(thread_array, + new_thread_array = realloc(thread_array, thread_count*sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); From 133d8a8ad8adb44c15185d67c3ae20069dd70521 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 01:24:50 +0200 Subject: [PATCH 1050/1232] .gitattributes: make sure docs/nut.dict is always LF (no CR) Signed-off-by: Jim Klimov --- .gitattributes | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitattributes b/.gitattributes index 356235e246..b2943eda2f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,6 +8,14 @@ *.am text eol=lf *.hwdb text eol=lf +# Aspell claims issues finding `utf-8\r` sometimes (from heading line of +# the dictionary file), with messages like this: +# .cset" could not be opened for reading or does not exist.lib/aspell/utf-8 +# which tends to happen in mixed-OS development environments. Tracer shows it: +# read(3, "personal_ws-1.1 en 3225 utf-8\r\nA"..., 4096) = 4096 +# access("/usr/lib/aspell/utf-8\r.cset", F_OK) = -1 ENOENT (No such file or directory) +/docs/nut.dict text eol=lf + # Some files are binary always: *.png bin *.ico bin From 28812cb6b84b96133a143cf17d356eaf9e6c33cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 13:36:47 +0000 Subject: [PATCH 1051/1232] drivers/ever-hid.c: fix "powerfactor" without a namespace Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ drivers/ever-hid.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index c45c3ee4ba..1df35b898e 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -154,6 +154,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. devices with ProductID 0x0601 as done earlier for 0x0501, to get the correct output voltage data [#1497] * apc-hid subdriver now also supports ProductID 0x0004 [#1429] + * ever-hid subdriver reported a `powerfactor` without a namespace (bug + in 2.8.0 release), fixed to `outlet.powerfactor` * the `usbhid-ups` driver should now reconnect if `libusb` returned a memory allocation error [#1422] (seen as "Can't retrieve Report 0a: Resource temporarily unavailable"), which can cause practical problems diff --git a/drivers/ever-hid.c b/drivers/ever-hid.c index 609b18076a..522931247c 100644 --- a/drivers/ever-hid.c +++ b/drivers/ever-hid.c @@ -33,7 +33,7 @@ #include "main.h" /* for getval() */ #include "usb-common.h" -#define EVER_HID_VERSION "Ever HID 0.1" +#define EVER_HID_VERSION "Ever HID 0.10" /* FIXME: experimental flag to be put in upsdrv_info */ /* Ever */ @@ -533,7 +533,7 @@ static hid_info_t ever_hid2nut[] = { /* WAS: "experimental.inverter_info.battery_temperature" */ { "battery.temperature", 0, 0, "UPS.EVER1.EVER43", NULL, "%s", 0, kelvin_celsius_conversion }, /* WAS: "experimental.ups_info.output_powerfactor" */ - { "powerfactor", 0, 0, "UPS.EVER1.EVER44", NULL, "%.0f", 0, NULL }, + { "output.powerfactor", 0, 0, "UPS.EVER1.EVER44", NULL, "%.0f", 0, NULL }, /* experimental: Should these be HU_TYPE_CMD entries? * Or are they really settings? */ From 968ed25666cc18317e64387bc9a39a987fd6e46a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 13:46:09 +0000 Subject: [PATCH 1052/1232] docs/nut.dict: Update with words missing in some platform default dictionaries 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 9e477f30c7..af07d51f3c 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3225 utf-8 +personal_ws-1.1 en 3230 utf-8 AAS ABI ACFAIL @@ -292,6 +292,7 @@ Dharm DiSplay Diehl Dietze +Disassembly Digitus Digys Dimitris @@ -1727,6 +1728,7 @@ collectd colspan command's commandlen +committer compat compilerPath conf @@ -1828,6 +1830,7 @@ dialout difftool dipsw dir +disassembly discardable disp distcheck @@ -1847,6 +1850,7 @@ dockapp docs dod domxml +downloadable dpkg dq driverexec @@ -3135,6 +3139,7 @@ ver verifySourceSig versa versioned +versioning victron victronups vid From af311f8b66dac2dbb659c7ba982afcec9f831edd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 19:00:15 +0200 Subject: [PATCH 1053/1232] ci_build.sh: introduce initial clean-up shortcut (used if recipes change) Signed-off-by: Jim Klimov --- ci_build.sh | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 7cce57ad94..52d9ff75ba 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1296,6 +1296,19 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # older system) we have to remove it when we already have the script. # This matches the use-case of distro-building from release tarballs that # include all needed pre-generated files to rely less on OS facilities. + if [ -s Makefile ]; then + if [ -n "`find "${SCRIPTDIR}" -name configure.ac -newer "${CI_BUILDDIR}"/configure`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name '*.m4' -newer "${CI_BUILDDIR}"/configure`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.am -newer "${CI_BUILDDIR}"/Makefile`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.in -newer "${CI_BUILDDIR}"/Makefile`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.am -newer "${CI_BUILDDIR}"/Makefile.in`" ] \ + ; then + # Avoid reconfiguring for the sake of distclean + echo "=== Starting initial clean-up (from old build products): TAKING SHORTCUT because recipes changed" + rm -f "${CI_BUILDDIR}"/Makefile "${CI_BUILDDIR}"/configure + fi + fi + if [ -s Makefile ]; then # Let initial clean-up be at default verbosity @@ -1891,6 +1904,19 @@ bindings) fi cd "${SCRIPTDIR}" + if [ -s Makefile ]; then + if [ -n "`find "${SCRIPTDIR}" -name configure.ac -newer "${CI_BUILDDIR}"/configure`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name '*.m4' -newer "${CI_BUILDDIR}"/configure`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.am -newer "${CI_BUILDDIR}"/Makefile`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.in -newer "${CI_BUILDDIR}"/Makefile`" ] \ + || [ -n "`find "${SCRIPTDIR}" -name Makefile.am -newer "${CI_BUILDDIR}"/Makefile.in`" ] \ + ; then + # Avoid reconfiguring for the sake of distclean + echo "=== Starting initial clean-up (from old build products): TAKING SHORTCUT because recipes changed" + rm -f "${CI_BUILDDIR}"/Makefile "${CI_BUILDDIR}"/configure + fi + fi + if [ -s Makefile ]; then # Help developers debug: # Let initial clean-up be at default verbosity From b7a14b3c8062fcbb0d4fa3c872cfd754ae0f968b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 22:07:30 +0200 Subject: [PATCH 1054/1232] m4/nut_check_libregex.m4: move detection from m4/nut_check_libusb.m4; adapt configure.ac and */Makefile.am accordingly Signed-off-by: Jim Klimov --- configure.ac | 11 +++-- drivers/Makefile.am | 1 + m4/nut_check_libregex.m4 | 100 +++++++++++++++++++++++++++++++++++++++ m4/nut_check_libusb.m4 | 7 ++- 4 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 m4/nut_check_libregex.m4 diff --git a/configure.ac b/configure.ac index b2619d2c90..5f22c4d02a 100644 --- a/configure.ac +++ b/configure.ac @@ -193,13 +193,17 @@ if test ! -d "${auglensdir}"; then fi fi -LIBREGEX_LIBS='' +dnl ### NUT_CHECK_LIBREGEX ### Detect below as part of libusb etc. +dnl ### LIBREGEX_LIBS='' dnl Disable Hotplug, DevD and udev support on Windows dnl (useful when cross-compiling) case "${target_os}" in *mingw* ) - dnl TODO: Actually detect it? See also nut_check_libusb.m4 for same. - LIBREGEX_LIBS='-lregex' + dnl TODO: Actually detect it? See also nut_check_libregex.m4 for same. + dnl Here we assumed from practice that it is available... + dnl ### if test x"${LIBREGEX_LIBS}" = x ; then + dnl ### LIBREGEX_LIBS='-lregex' + dnl ### fi hotplugdir='' udevdir='' devddir='' @@ -1522,6 +1526,7 @@ dnl These checks are performed unconditionally, even if the corresponding dnl --with-* options are not given. This is because we cannot predict dnl what will be in the --with-drivers argument. +NUT_CHECK_LIBREGEX NUT_ARG_WITH([usb], [build and install USB drivers, optionally require build with specified version of libusb library and API: (auto|libusb-0.1|libusb-1.0)], [auto]) nut_usb_lib="" NUT_CHECK_LIBUSB diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 3d945abd2f..747a97a9ed 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -124,6 +124,7 @@ upsdrvctl_LDADD = $(LDADD_COMMON) libdummy_upsdrvquery.la # serial drivers: all of them use standard LDADD and CFLAGS al175_SOURCES = al175.c apcsmart_SOURCES = apcsmart.c apcsmart_tabs.c +apcsmart_CFLAGS = $(LIBREGEX_CFLAGS) apcsmart_LDADD = $(LDADD) $(LIBREGEX_LIBS) apcsmart_old_SOURCES = apcsmart-old.c bcmxcp_SOURCES = bcmxcp.c bcmxcp_ser.c diff --git a/m4/nut_check_libregex.m4 b/m4/nut_check_libregex.m4 new file mode 100644 index 0000000000..6a3a4c8f02 --- /dev/null +++ b/m4/nut_check_libregex.m4 @@ -0,0 +1,100 @@ +dnl Check for LIBREGEX (and, if found, fill 'nut_usb_lib' with its +dnl approximate version) and its compiler flags. On success, set +dnl nut_have_libusb="yes" and set LIBREGEX_CFLAGS and LIBREGEX_LIBS. On failure, set +dnl nut_have_libusb="no". This macro can be run multiple times, but will +dnl do the checking only once. + +AC_DEFUN([NUT_CHECK_LIBREGEX], +[ +if test -z "${nut_have_libregex_seen}"; then + nut_have_libregex_seen=yes + NUT_CHECK_PKGCONFIG + + dnl save CFLAGS and LIBS + CFLAGS_ORIG="${CFLAGS}" + LIBS_ORIG="${LIBS}" + CFLAGS="" + LIBS="" + + dnl Actually did not see it in any systems' pkg-config info... + dnl Part of standard footprint? + LIBREGEX_MODULE="" + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [AC_MSG_CHECKING(for libregex version via pkg-config) + LIBREGEX_VERSION="`$PKG_CONFIG --silence-errors --modversion regex 2>/dev/null`" + if test "$?" != "0" -o -z "${LIBREGEX_VERSION}"; then + LIBREGEX_VERSION="`$PKG_CONFIG --silence-errors --modversion libregex 2>/dev/null`" + if test "$?" != "0" -o -z "${LIBREGEX_VERSION}"; then + LIBREGEX_VERSION="none" + else + LIBREGEX_MODULE="libregex" + fi + else + LIBREGEX_MODULE="regex" + fi + AC_MSG_RESULT(${LIBREGEX_VERSION} found) + ], + [LIBREGEX_VERSION="none" + AC_MSG_NOTICE([can not check libregex settings via pkg-config]) + ] + ) + + AS_IF([test x"$LIBREGEX_VERSION" != xnone && test x"$LIBREGEX_MODULE" != x], + [CFLAGS="`$PKG_CONFIG --silence-errors --cflags "${LIBREGEX_MODULE}" 2>/dev/null`" + LIBS="`$PKG_CONFIG --silence-errors --libs "${LIBREGEX_MODULE}" 2>/dev/null`" + REQUIRES="${LIBREGEX_MODULE}" + ], + [CFLAGS="" + LIBS="" + REQUIRES="" + ] + ) + + dnl Check if libregex is usable + AC_LANG_PUSH([C]) + dnl # With USB we can match desired devices by regex + dnl # (and currently have no other use for the library); + dnl # however we may have some general regex helper + dnl # methods built into libcommon (may become useful + dnl # elsewhere) - so need to know if we may and should. + dnl # Maybe already involved in NUT for Windows builds... + nut_have_regex=no + AC_CHECK_HEADER([regex.h], + [nut_have_regex=yes + AC_DEFINE([HAVE_REGEX_H], [1], + [Define to 1 if you have .])]) + AC_CHECK_DECLS([regexec, regcomp], [nut_have_regex=yes], [], +[#ifdef HAVE_REGEX_H +# include +#endif +]) + + AC_SEARCH_LIBS([regcomp, regexec], [], [nut_have_regex=yes], [ + AS_IF([test x"$LIBS" = x], [ + AC_SEARCH_LIBS([regcomp, regexec], [regex], [ + LIBS="-lregex" + nut_have_regex=yes + ]) + ]) + ]) + + AS_IF([test x"${nut_have_regex}" = xyes], [ + LIBREGEX_CFLAGS="${CFLAGS}" + LIBREGEX_LIBS="${LIBS}" + AC_DEFINE(HAVE_LIBREGEX, 1, + [Define to 1 for build where we can support general regex matching.]) + ], [ + LIBREGEX_CFLAGS="" + LIBREGEX_LIBS="" + AC_DEFINE(HAVE_LIBREGEX, 0, + [Define to 1 for build where we can support general regex matching.]) + ]) + AM_CONDITIONAL(HAVE_LIBREGEX, test x"${nut_have_regex}" = xyes) + + AC_LANG_POP([C]) + + dnl restore original CFLAGS and LIBS + CFLAGS="${CFLAGS_ORIG}" + LIBS="${LIBS_ORIG}" +fi +]) diff --git a/m4/nut_check_libusb.m4 b/m4/nut_check_libusb.m4 index 5b042b0790..186e7c6e2f 100644 --- a/m4/nut_check_libusb.m4 +++ b/m4/nut_check_libusb.m4 @@ -14,6 +14,9 @@ if test -z "${nut_have_libusb_seen}"; then nut_have_libusb_seen=yes NUT_CHECK_PKGCONFIG + dnl Our USB matching relies on regex abilities + NUT_CHECK_LIBREGEX + dnl save CFLAGS and LIBS CFLAGS_ORIG="${CFLAGS}" LIBS_ORIG="${LIBS}" @@ -325,10 +328,6 @@ if test -z "${nut_have_libusb_seen}"; then dnl DEFINE WITH_USB_BUSPORT dnl #endif AC_CHECK_FUNCS(libusb_get_port_number, [nut_with_usb_busport=yes]) - - dnl # With USB we can match desired devices by regex; - dnl # and currently have no other use for the library: - AC_SEARCH_LIBS(regcomp, regex) ]) AC_LANG_POP([C]) From 0897c9f2d9b323864e978fd837a54f724e4f1dbd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 22:08:53 +0200 Subject: [PATCH 1055/1232] common.{c,h}: move here general REGEX helper methods from drivers/usb-common.{c,h} [#1369] Signed-off-by: Jim Klimov --- common/Makefile.am | 8 +++ common/common.c | 106 ++++++++++++++++++++++++++++++++++++ drivers/usb-common.c | 126 ------------------------------------------- include/common.h | 40 ++++++++++++++ 4 files changed, 154 insertions(+), 126 deletions(-) diff --git a/common/Makefile.am b/common/Makefile.am index e30efd6428..a6914d6698 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -76,6 +76,14 @@ libcommonclient_la_LIBADD = libparseconf.la @LTLIBOBJS@ @NETLIBS@ libcommon_la_CFLAGS = $(AM_CFLAGS) libcommonclient_la_CFLAGS = $(AM_CFLAGS) +if HAVE_LIBREGEX + libcommon_la_CFLAGS += $(LIBREGEX_CFLAGS) + libcommon_la_LIBADD += $(LIBREGEX_LIBS) + + libcommonclient_la_CFLAGS += $(LIBREGEX_CFLAGS) + libcommonclient_la_LIBADD += $(LIBREGEX_LIBS) +endif + # Did the user request, and build env support, tighter integration with # libsystemd methods such as sd_notify()? if WITH_LIBSYSTEMD diff --git a/common/common.c b/common/common.c index d91a9d368f..16228665a5 100644 --- a/common/common.c +++ b/common/common.c @@ -2126,3 +2126,109 @@ void set_close_on_exec(int fd) { # endif #endif } + +/**** REGEX helper methods ****/ + +int strcmp_null(const char *s1, const char *s2) +{ + if (s1 == NULL && s2 == NULL) { + return 0; + } + + if (s1 == NULL) { + return -1; + } + + if (s2 == NULL) { + return 1; + } + + return strcmp(s1, s2); +} + +#if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) +int compile_regex(regex_t **compiled, const char *regex, const int cflags) +{ + int r; + regex_t *preg; + + if (regex == NULL) { + *compiled = NULL; + return 0; + } + + preg = malloc(sizeof(*preg)); + if (!preg) { + return -1; + } + + r = regcomp(preg, regex, cflags); + if (r) { + free(preg); + return -2; + } + + *compiled = preg; + + return 0; +} + +int match_regex(const regex_t *preg, const char *str) +{ + int r; + size_t len = 0; + char *string; + regmatch_t match; + + if (!preg) { + return 1; + } + + if (!str) { + string = xstrdup(""); + } else { + /* skip leading whitespace */ + for (len = 0; len < strlen(str); len++) { + + if (!strchr(" \t\n", str[len])) { + break; + } + } + + string = xstrdup(str+len); + + /* skip trailing whitespace */ + for (len = strlen(string); len > 0; len--) { + + if (!strchr(" \t\n", string[len-1])) { + break; + } + } + + string[len] = '\0'; + } + + /* test the regular expression */ + r = regexec(preg, string, 1, &match, 0); + free(string); + if (r) { + return 0; + } + + /* check that the match is the entire string */ + if ((match.rm_so != 0) || (match.rm_eo != (int)len)) { + return 0; + } + + return 1; +} + +int match_regex_hex(const regex_t *preg, const int n) +{ + char buf[10]; + + snprintf(buf, sizeof(buf), "%04x", n); + + return match_regex(preg, buf); +} +#endif /* HAVE_LIBREGEX */ diff --git a/drivers/usb-common.c b/drivers/usb-common.c index d3bc96748b..ccdb104a59 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -54,27 +54,6 @@ int is_usb_device_supported(usb_device_id_t *usb_device_id_list, USBDevice_t *de /* ---------------------------------------------------------------------- */ /* matchers */ -/* helper function: version of strcmp that tolerates NULL - * pointers. NULL is considered to come before all other strings - * alphabetically. - */ -static int strcmp_null(char *s1, char *s2) -{ - if (s1 == NULL && s2 == NULL) { - return 0; - } - - if (s1 == NULL) { - return -1; - } - - if (s2 == NULL) { - return 1; - } - - return strcmp(s1, s2); -} - /* private callback function for exact matches */ static int match_function_exact(USBDevice_t *hd, void *privdata) @@ -202,111 +181,6 @@ void USBFreeExactMatcher(USBDeviceMatcher_t *matcher) free(matcher); } -/* Private function for compiling a regular expression. On success, - * store the compiled regular expression (or NULL) in *compiled, and - * return 0. On error with errno set, return -1. If the supplied - * regular expression is unparseable, return -2 (an error message can - * then be retrieved with regerror(3)). Note that *compiled will be an - * allocated value, and must be freed with regfree(), then free(), see - * regex(3). As a special case, if regex==NULL, then set - * *compiled=NULL (regular expression NULL is intended to match - * anything). - */ -static int compile_regex(regex_t **compiled, char *regex, int cflags) -{ - int r; - regex_t *preg; - - if (regex == NULL) { - *compiled = NULL; - return 0; - } - - preg = malloc(sizeof(*preg)); - if (!preg) { - return -1; - } - - r = regcomp(preg, regex, cflags); - if (r) { - free(preg); - return -2; - } - - *compiled = preg; - - return 0; -} - -/* Private function for regular expression matching. Check if the - * entire string str (minus any initial and trailing whitespace) - * matches the compiled regular expression preg. Return 1 if it - * matches, 0 if not. Return -1 on error with errno set. Special - * cases: if preg==NULL, it matches everything (no contraint). If - * str==NULL, then it is treated as "". - */ -static int match_regex(regex_t *preg, char *str) -{ - int r; - size_t len = 0; - char *string; - regmatch_t match; - - if (!preg) { - return 1; - } - - if (!str) { - string = xstrdup(""); - } else { - /* skip leading whitespace */ - for (len = 0; len < strlen(str); len++) { - - if (!strchr(" \t\n", str[len])) { - break; - } - } - - string = xstrdup(str+len); - - /* skip trailing whitespace */ - for (len = strlen(string); len > 0; len--) { - - if (!strchr(" \t\n", string[len-1])) { - break; - } - } - - string[len] = '\0'; - } - - /* test the regular expression */ - r = regexec(preg, string, 1, &match, 0); - free(string); - if (r) { - return 0; - } - - /* check that the match is the entire string */ - if ((match.rm_so != 0) || (match.rm_eo != (int)len)) { - return 0; - } - - return 1; -} - -/* Private function, similar to match_regex, but the argument being - * matched is a (hexadecimal) number, rather than a string. It is - * converted to a 4-digit hexadecimal string. */ -static int match_regex_hex(regex_t *preg, int n) -{ - char buf[10]; - - snprintf(buf, sizeof(buf), "%04x", n); - - return match_regex(preg, buf); -} - /* private data type: hold a set of compiled regular expressions. */ typedef struct regex_matcher_data_s { regex_t *regex[USBMATCHER_REGEXP_ARRAY_LIMIT]; diff --git a/include/common.h b/include/common.h index 3d0052f8fd..31a10a8fc4 100644 --- a/include/common.h +++ b/include/common.h @@ -85,6 +85,10 @@ #include "proto.h" #include "str.h" +#if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) +# include +#endif + #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { @@ -338,6 +342,42 @@ void *xcalloc(size_t number, size_t size); void *xrealloc(void *ptr, size_t size); char *xstrdup(const char *string); +/**** REGEX helper methods ****/ + +/* helper function: version of strcmp that tolerates NULL + * pointers. NULL is considered to come before all other strings + * alphabetically. + */ +int strcmp_null(const char *s1, const char *s2); + +#if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) +/* Helper function for compiling a regular expression. On success, + * store the compiled regular expression (or NULL) in *compiled, and + * return 0. On error with errno set, return -1. If the supplied + * regular expression is unparseable, return -2 (an error message can + * then be retrieved with regerror(3)). Note that *compiled will be an + * allocated value, and must be freed with regfree(), then free(), see + * regex(3). As a special case, if regex==NULL, then set + * *compiled=NULL (regular expression NULL is intended to match + * anything). + */ +int compile_regex(regex_t **compiled, const char *regex, const int cflags); + +/* Helper function for regular expression matching. Check if the + * entire string str (minus any initial and trailing whitespace) + * matches the compiled regular expression preg. Return 1 if it + * matches, 0 if not. Return -1 on error with errno set. Special + * cases: if preg==NULL, it matches everything (no contraint). If + * str==NULL, then it is treated as "". + */ +int match_regex(const regex_t *preg, const char *str); + +/* Helper function, similar to match_regex, but the argument being + * matched is a (hexadecimal) number, rather than a string. It is + * converted to a 4-digit hexadecimal string. */ +int match_regex_hex(const regex_t *preg, const int n); +#endif /* HAVE_LIBREGEX */ + /* Note: different method signatures instead of TYPE_FD_SER due to "const" */ #ifndef WIN32 ssize_t select_read(const int fd, void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec); From e029089ecf784fbb8012d18ed2e3cc4d3fb700ac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 22:38:17 +0200 Subject: [PATCH 1056/1232] clients/Makefile.am: build clients against libcommonclient.la (fewer link and run-time deps pulled), not libcommon.la Signed-off-by: Jim Klimov --- clients/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clients/Makefile.am b/clients/Makefile.am index 8a2dd61991..d38a6a5bf2 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -12,8 +12,9 @@ $(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libparseconf.la: dummy @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) -# by default, link programs in this directory with libcommon.a -LDADD = $(top_builddir)/common/libcommon.la libupsclient.la $(NETLIBS) +# by default, link programs in this directory with +# the more compact libcommonclient.a bundle +LDADD = $(top_builddir)/common/libcommonclient.la libupsclient.la $(NETLIBS) if WITH_SSL LDADD += $(LIBSSL_LIBS) endif From 91eda53a4f466e1df9090e9e3011a5a5138f3488 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 22:11:20 +0200 Subject: [PATCH 1057/1232] drivers/usbhid-ups.c: implement match_function_subdriver_name() for "subdriver" matching option; update docs about it [#1369] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++ docs/man/usbhid-ups.txt | 12 ++++++ drivers/usbhid-ups.c | 87 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 18609d78d9..b9e7b4495c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -152,6 +152,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * extended default ranges for max battery voltage when guessing [#1279] - usbhid-ups updates: + * added support for `subdriver` configuration option, to select the + USB HID subdriver for the device manually where automatic match + does not suffice (e.g. new devices for which no `vendorid`/`productid` + pair was built into any driver, or for different-capability devices + with same interface chips, notably "phoenixtec/liebert" and "mge") [#1369] * cps-hid subdriver now applies same report descriptor fixing logic to devices with ProductID 0x0601 as done earlier for 0x0501, to get the correct output voltage data [#1497] diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index 9b86737991..098844abaa 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -54,6 +54,18 @@ This driver also supports the following optional settings: include::nut_usb_addvars.txt[] +*subdriver*='regex':: +Select the USB HID subdriver for the device manually, where automatic match +by device attributes alone does not suffice (e.g. new devices for which no +`vendorid`/`productid` pair was built into any driver -- but common USB HID +support is anticipated, or for different-capability devices with same +interface chips, notably "phoenixtec/liebert" and "mge"). ++ +NOTE: this option first checks for exact matches to subdriver identification +strings, such as `"TrippLite HID 0.85"` (which are prone to bit-rot), and if +there was no exact match -- retries with a case-insensitive extended regular +expression. + *offdelay*='num':: Set the timer before the UPS is turned off after the kill power command is sent (via the *-k* switch). diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 36748c66fb..beb32d6e45 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -28,16 +28,17 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.51" +#define DRIVER_VERSION "0.52" #define HU_VAR_WAITBEFORERECONNECT "waitbeforereconnect" -#include "main.h" +#include "main.h" /* Must be first, includes "config.h" */ #include "nut_stdint.h" #include "libhid.h" #include "usbhid-ups.h" #include "hidparser.h" #include "hidtypes.h" +#include "common.h" #ifdef WIN32 #include "wincompat.h" #endif @@ -531,6 +532,67 @@ info_lkp_t kelvin_celsius_conversion[] = { { 0, NULL, kelvin_celsius_conversion_fun, NULL } }; +static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { + char *subdrv = getval("subdriver"); + + /* Pick up the subdriver name if set explicitly */ + if (subdrv) { + int res, i, flag_HAVE_LIBREGEX = 0; +#if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) + regex_t *regex_ptr = NULL; + flag_HAVE_LIBREGEX = 1; +#endif + + upsdebugx(2, + "%s: matching a subdriver by explicit " + "name%s: '%s'...", + __func__, + flag_HAVE_LIBREGEX ? "/regex" : "", + subdrv); + + /* First try exact match for strings like "TrippLite HID 0.85" + * Not likely to hit (due to versions etc.), but worth a try :) + */ + for (i=0; subdriver_list[i] != NULL; i++) { + if (strcmp_null(subdrv, subdriver_list[i]->name) == 0) { + return subdriver_list[i]; + } + } + +#if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) + /* Then try a case-insensitive regex like "tripplite" */ + res = compile_regex(®ex_ptr, subdrv, REG_ICASE | REG_EXTENDED); + if (res == 0 && regex_ptr != NULL) { + for (i=0; subdriver_list[i] != NULL; i++) { + res = match_regex(regex_ptr, subdriver_list[i]->name); + if (res == 1) { + free(regex_ptr); + return subdriver_list[i]; + } + } + } + + if (regex_ptr) + free(regex_ptr); +#endif /* HAVE_LIBREGEX */ + + if (fatal_mismatch) { + fatalx(EXIT_FAILURE, + "Configuration requested subdriver '%s' but none matched", + subdrv); + } else { + upslogx(LOG_WARNING, + "Configuration requested subdriver '%s' but none matched; " + "will try USB matching by other fields", + subdrv); + } + } + + /* No match (and non-fatal mismatch mode), or no + * "subdriver" was specified in configuration */ + return NULL; +} + /*! * subdriver matcher: only useful for USB mode * as SHUT is only supported by MGE UPS SYSTEMS units @@ -538,9 +600,14 @@ info_lkp_t kelvin_celsius_conversion[] = { #if !((defined SHUT_MODE) && SHUT_MODE) static int match_function_subdriver(HIDDevice_t *d, void *privdata) { - int i; + int i; NUT_UNUSED_VARIABLE(privdata); + if (match_function_subdriver_name(1)) { + /* This driver can handle this device. Guessing so... */ + return 1; + } + upsdebugx(2, "%s (non-SHUT mode): matching a device...", __func__); for (i=0; subdriver_list[i] != NULL; i++) { @@ -809,6 +876,8 @@ void upsdrv_makevartable(void) "Set to disable fix-ups for broken USB encoding, etc. which we apply by default on certain vendors/products"); #if !((defined SHUT_MODE) && SHUT_MODE) + addvar(VAR_VALUE, "subdriver", "Explicit USB HID subdriver selection"); + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ nut_usb_addvars(); @@ -1294,13 +1363,17 @@ static int callback( } /* select the subdriver for this device */ - for (i=0; subdriver_list[i] != NULL; i++) { - if (subdriver_list[i]->claim(hd)) { - break; + subdriver = match_function_subdriver_name(0); + if (!subdriver) { + for (i=0; subdriver_list[i] != NULL; i++) { + if (subdriver_list[i]->claim(hd)) { + break; + } } + + subdriver = subdriver_list[i]; } - subdriver = subdriver_list[i]; if (!subdriver) { upsdebugx(1, "Manufacturer not supported!"); return 0; From 9289fbc751439105b42e815b78f98261be0fc38d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 23:27:28 +0200 Subject: [PATCH 1058/1232] drivers/usbhid-ups.c: match_function_subdriver_name(): automate use of regex "somename.*" [#1369] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index beb32d6e45..8ec5bfa15d 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -538,6 +538,7 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { /* Pick up the subdriver name if set explicitly */ if (subdrv) { int res, i, flag_HAVE_LIBREGEX = 0; + size_t len; #if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) regex_t *regex_ptr = NULL; flag_HAVE_LIBREGEX = 1; @@ -560,7 +561,9 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { } #if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) - /* Then try a case-insensitive regex like "tripplite" */ + /* Then try a case-insensitive regex like "tripplite.*" + * if so provided by caller */ + upsdebugx(2, "%s: retry matching by regex 'as is'", __func__); res = compile_regex(®ex_ptr, subdrv, REG_ICASE | REG_EXTENDED); if (res == 0 && regex_ptr != NULL) { for (i=0; subdriver_list[i] != NULL; i++) { @@ -572,8 +575,38 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { } } - if (regex_ptr) + if (regex_ptr) { free(regex_ptr); + regex_ptr = NULL; + } + + /* Then try a case-insensitive regex like "tripplite.*" + * with automatically added ".*" */ + len = strlen(subdrv); + if ( + (len < 3 || (subdrv[len-2] != '.' && subdrv[len-1] != '*')) + && len < (LARGEBUF-3) + ) { + char buf[LARGEBUF]; + upsdebugx(2, "%s: retry matching by regex with added '.*'", __func__); + snprintf(buf, sizeof(buf), "%s.*", subdrv); + res = compile_regex(®ex_ptr, buf, REG_ICASE | REG_EXTENDED); + if (res == 0 && regex_ptr != NULL) { + for (i=0; subdriver_list[i] != NULL; i++) { + res = match_regex(regex_ptr, subdriver_list[i]->name); + if (res == 1) { + free(regex_ptr); + return subdriver_list[i]; + } + } + } + + if (regex_ptr) { + free(regex_ptr); + regex_ptr = NULL; + } + } + #endif /* HAVE_LIBREGEX */ if (fatal_mismatch) { From e1b0320413949bf556bf4effa5ec0dd8be0206b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 23:30:35 +0200 Subject: [PATCH 1059/1232] drivers/usbhid-ups.c: match_function_subdriver_name(): report the name of found USB HID subdriver [#1369] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 8ec5bfa15d..17600bb8eb 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -534,6 +534,7 @@ info_lkp_t kelvin_celsius_conversion[] = { static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { char *subdrv = getval("subdriver"); + subdriver_t *info = NULL; /* Pick up the subdriver name if set explicitly */ if (subdrv) { @@ -556,7 +557,8 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { */ for (i=0; subdriver_list[i] != NULL; i++) { if (strcmp_null(subdrv, subdriver_list[i]->name) == 0) { - return subdriver_list[i]; + info = subdriver_list[i]; + goto found; } } @@ -570,7 +572,8 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { res = match_regex(regex_ptr, subdriver_list[i]->name); if (res == 1) { free(regex_ptr); - return subdriver_list[i]; + info = subdriver_list[i]; + goto found; } } } @@ -596,7 +599,8 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { res = match_regex(regex_ptr, subdriver_list[i]->name); if (res == 1) { free(regex_ptr); - return subdriver_list[i]; + info = subdriver_list[i]; + goto found; } } } @@ -624,6 +628,10 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { /* No match (and non-fatal mismatch mode), or no * "subdriver" was specified in configuration */ return NULL; + +found: + upsdebugx(2, "%s: found a match: %s", __func__, info->name); + return info; } /*! From 44b64e1d0a587693ff2e8b03fc0f18db8fb3e18a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 23:52:06 +0200 Subject: [PATCH 1060/1232] drivers/usbhid-ups.c: match_function_subdriver_name(): require (or recommend) vendorid/productid [#1369] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 17600bb8eb..9bb9119942 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -631,6 +631,20 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { found: upsdebugx(2, "%s: found a match: %s", __func__, info->name); + if (!getval("vendorid") || !getval("productid")) { + if (fatal_mismatch) { + fatalx(EXIT_FAILURE, + "When specifying a subdriver, " + "'vendorid' and 'productid' " + "are mandatory."); + } else { + upslogx(LOG_WARNING, + "When specifying a subdriver, " + "'vendorid' and 'productid' " + "are highly recommended."); + } + } + return info; } From 98ecf015d8d8354fc8079ee186905e21462fd362 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 12:54:25 +0000 Subject: [PATCH 1061/1232] configure.ac: hush down some more clang "-Wextra" or "-Weverything" warnings that we can not really address [#2055, #823] Signed-off-by: Jim Klimov --- configure.ac | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 5f22c4d02a..f7353f286d 100644 --- a/configure.ac +++ b/configure.ac @@ -4073,6 +4073,14 @@ dnl # -Wno-padded -- NSPR and NSS headers get to issue lots of that dnl # -Wno-c++98-compat-pedantic -Wno-c++98-compat -- our C++ code uses nullptr dnl # as requested by newer linters, and C++98 does not. We require C++11 dnl # or newer anyway, and skip building C++ library and test otherwise. +dnl # -Wno-fuse-ld-path -- not much in our control what recipes the autotools +dnl # on the build host generate... this tries to avoid failures due to: +dnl # clang-13: error: '-fuse-ld=' taking a path is deprecated. +dnl # Use '--ld-path=' instead [-Werror,-Wfuse-ld-path] +dnl # -Wno-unsafe-buffer-usage -- clang-16 introduced a check too smart for +dnl # its own good. It detects use of pointer aritmetics as arrays are +dnl # walked, which is indeed potentially dangerous. And also is nearly +dnl # unavoidable in C (at least not without major rewrites of the world). dnl ### Special exclusion picks for clang-medium (same as hard, plus...): dnl # -Wno-float-conversion -Wno-double-promotion -Wno-implicit-float-conversion dnl # -- reduce noise due to floating-point literals like "3.14" being a C @@ -4103,12 +4111,12 @@ AS_CASE(["${nut_enable_warnings}"], CXXFLAGS="${CXXFLAGS} -Wall" ], [clang-hard], [ - CFLAGS="${CFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -pedantic" - CXXFLAGS="${CXXFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-c++98-compat" + CFLAGS="${CFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -pedantic -Wno-fuse-ld-path -Wno-unsafe-buffer-usage" + CXXFLAGS="${CXXFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-fuse-ld-path -Wno-unsafe-buffer-usage" ], [clang-medium], [ - CFLAGS="${CFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -pedantic -Wno-float-conversion -Wno-double-promotion -Wno-implicit-float-conversion -Wno-conversion -Wno-incompatible-pointer-types-discards-qualifiers" - CXXFLAGS="${CXXFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-c++98-compat" + CFLAGS="${CFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -pedantic -Wno-fuse-ld-path -Wno-unsafe-buffer-usage -Wno-float-conversion -Wno-double-promotion -Wno-implicit-float-conversion -Wno-conversion -Wno-incompatible-pointer-types-discards-qualifiers" + CXXFLAGS="${CXXFLAGS} -ferror-limit=0 -Wno-system-headers -Wall -Wextra -Weverything -Wno-disabled-macro-expansion -Wno-unused-macros -Wno-reserved-id-macro -Wno-padded -Wno-documentation -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-fuse-ld-path -Wno-unsafe-buffer-usage" ], [clang-minimal], [ CFLAGS="${CFLAGS} -ferror-limit=0 -Wall -Wextra -Wno-documentation" From 697ca394114794654bcf2134aed2aba6410fa64a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 13:23:12 +0000 Subject: [PATCH 1062/1232] tools/nut-scanner/nutscan-display.c: report trailing blanks in serial numbers Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-display.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index 9cfa2716ec..c031889a82 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -294,7 +294,7 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) goto exit; } - /* Now look for red flags in the map */ + /* Now look for red flags in the map (key=sernum, val=device(s)) */ /* FIXME: Weed out special chars to avoid breaking comment-line markup? * Thinking of ASCII control codes < 32 including CR/LF, and codes 128+... */ for (i = 0; i < count; i++) { @@ -308,6 +308,13 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) continue; } + j = strlen(entry->key); + if (j > 0 && (entry->key[j-1] == '\t' || entry->key[j-1] == ' ')) { + printf("\n# WARNING: trailing blank space in \"serial\" " + "value \"%s\" reported in device configuration(s): %s", + entry->key, entry->val); + } + /* All chars in "serial" are same (zero, space, etc.) */ for (j = 0; entry->key[j] != '\0' && entry->key[j] == entry->key[0]; j++); if (j > 0 && entry->key[j] == '\0') { From fb6dcec2fc1a7b41d7bf3b4035e5b887252fe941 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 13:23:49 +0000 Subject: [PATCH 1063/1232] tools/nut-scanner/nutscan-display.c: do not drop out after the first (non-NULL) report, let all complaints be known Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index c031889a82..5c0f92f5b3 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -322,7 +322,6 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) "with %" PRIuSIZE " copies of '%c' (0x%02X) " "reported in some devices: %s\n", j, entry->key[0], entry->key[0], entry->val); - continue; } /* Duplicates (maybe same device, maybe not) */ @@ -334,7 +333,6 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) "likely a vendor bug if reported by same driver " "for many devices): %s\n", entry->key, entry->val); - continue; } } From 68ef74fd1a7bbb116dfecd5cf5e8b10f8ad500dc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 13:24:21 +0000 Subject: [PATCH 1064/1232] tools/nut-scanner/nutscan-display.c: fix report for "same serial in different devices" Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index 5c0f92f5b3..6539c166a4 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -324,9 +324,9 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) j, entry->key[0], entry->key[0], entry->val); } - /* Duplicates (maybe same device, maybe not) */ + /* Duplicates (maybe same device, maybe not) - see if val has a ',' */ for (j = 0; entry->val[j] != '\0' && entry->val[j] != ','; j++); - if (j > 0 && entry->key[j] != '\0') { + if (j > 0 && entry->val[j] != '\0') { printf("\n# WARNING: same \"serial\" value \"%s\" " "reported in several device configurations " "(maybe okay if multiple drivers for same device, " From 5cb6049e73792f38c912abdf83dcad0445b3e375 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 17:20:51 +0200 Subject: [PATCH 1065/1232] Update Makefile.am Steamline use of LIBREGEX_CFLAGS via AM_CFLAGS, same as others. Signed-off-by: Jim Klimov --- drivers/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 747a97a9ed..1a576f944b 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -38,6 +38,9 @@ endif if WITH_MODBUS AM_CFLAGS += $(LIBMODBUS_CFLAGS) endif +if HAVE_LIBREGEX + AM_CFLAGS += $(LIBREGEX_CFLAGS) +endif NUTSW_DRIVERLIST = dummy-ups clone clone-outlet apcupsd-ups skel SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ @@ -124,7 +127,6 @@ upsdrvctl_LDADD = $(LDADD_COMMON) libdummy_upsdrvquery.la # serial drivers: all of them use standard LDADD and CFLAGS al175_SOURCES = al175.c apcsmart_SOURCES = apcsmart.c apcsmart_tabs.c -apcsmart_CFLAGS = $(LIBREGEX_CFLAGS) apcsmart_LDADD = $(LDADD) $(LIBREGEX_LIBS) apcsmart_old_SOURCES = apcsmart-old.c bcmxcp_SOURCES = bcmxcp.c bcmxcp_ser.c From 28289ab8eab57ff95559d7ef027bf166af879653 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 19:20:18 +0000 Subject: [PATCH 1066/1232] m4/nut_check_libregex.m4: avoid using cached reply for the absent library name, when checking for -lregex Signed-off-by: Jim Klimov --- m4/nut_check_libregex.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/m4/nut_check_libregex.m4 b/m4/nut_check_libregex.m4 index 6a3a4c8f02..86c2bc1552 100644 --- a/m4/nut_check_libregex.m4 +++ b/m4/nut_check_libregex.m4 @@ -71,6 +71,8 @@ if test -z "${nut_have_libregex_seen}"; then AC_SEARCH_LIBS([regcomp, regexec], [], [nut_have_regex=yes], [ AS_IF([test x"$LIBS" = x], [ + dnl Avoid using cached reply for the absent library name + unset ac_cv_search_regcomp__regexec || true AC_SEARCH_LIBS([regcomp, regexec], [regex], [ LIBS="-lregex" nut_have_regex=yes From 93113806905d096f6affd88da8d49244ded50a30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 22:07:22 +0200 Subject: [PATCH 1067/1232] docs/man/nutdrv_qx.txt, docs/man/usbhid-ups.txt: update man page notes about subdriver settings [#1369] Signed-off-by: Jim Klimov --- docs/man/nutdrv_qx.txt | 7 ++++++- docs/man/usbhid-ups.txt | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index 71b11f1cd3..83f2a136d3 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -348,7 +348,12 @@ include::nut_usb_addvars.txt[] *subdriver =* 'string':: Select a serial-over-USB subdriver to use. You have a choice between *cypress*, *fabula*, *fuji*, *hunnox*, *ippon*, *krauler*, *phoenix*, *phoenixtec*, *sgs*, *snr*, *armac* and *ablerex*. -When using this option, it is mandatory to also specify the *vendorid* and *productid*. ++ +Run the driver program with the `--help` option to see the exact list of +`subdriver` values it would currently recognize. ++ +NOTE: When using this option, it is mandatory to also specify the *vendorid* +and *productid* matching parameters. *langid_fix =* 'value':: Apply the language ID workaround to the *krauler* subdriver. diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index 098844abaa..ac7c4aa43c 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -65,6 +65,9 @@ NOTE: this option first checks for exact matches to subdriver identification strings, such as `"TrippLite HID 0.85"` (which are prone to bit-rot), and if there was no exact match -- retries with a case-insensitive extended regular expression. ++ +NOTE: When using this option, it is mandatory to also specify the *vendorid* +and *productid* matching parameters. *offdelay*='num':: Set the timer before the UPS is turned off after the kill power command is From 166b762aa173844a87604dea20e18f485eb7b33c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 22:09:23 +0200 Subject: [PATCH 1068/1232] drivers/usbhid-ups.c, docs/man/usbhid-ups.txt: list available "subdriver" setting values in command-line usage request (--help) [#1369] Signed-off-by: Jim Klimov --- docs/man/usbhid-ups.txt | 3 +++ drivers/usbhid-ups.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index ac7c4aa43c..0a916fbc4f 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -61,6 +61,9 @@ by device attributes alone does not suffice (e.g. new devices for which no support is anticipated, or for different-capability devices with same interface chips, notably "phoenixtec/liebert" and "mge"). + +Run the driver program with the `--help` option to see the exact list of +`subdriver` values it would currently recognize. ++ NOTE: this option first checks for exact matches to subdriver identification strings, such as `"TrippLite HID 0.85"` (which are prone to bit-rot), and if there was no exact match -- retries with a case-insensitive extended regular diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 9bb9119942..800abe3bbe 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -893,7 +893,19 @@ void upsdrv_shutdown(void) void upsdrv_help(void) { - /* FIXME: to be completed */ + size_t i; + printf("\nAcceptable values for 'subdriver' via -x or ups.conf " + "in this driver (exact names here, case-insensitive " + "sub-strings may be used, as well as regular expressions): "); + + for (i = 0; subdriver_list[i] != NULL; i++) { + if (i>0) + printf(", "); + printf("\"%s\"", subdriver_list[i]->name); + } + printf("\n\n"); + + printf("Read The Fine Manual ('man 8 usbhid-ups')\n"); } void upsdrv_makevartable(void) From e8e7dc5e641a31298101a89dc9dd85b002001e32 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 22:09:59 +0200 Subject: [PATCH 1069/1232] drivers/nutdrv_qx.c, docs/man/nutdrv_qx.txt: list available "protocol" setting values in command-line usage request (--help) [#1369] Signed-off-by: Jim Klimov --- docs/man/nutdrv_qx.txt | 3 +++ drivers/nutdrv_qx.c | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/docs/man/nutdrv_qx.txt b/docs/man/nutdrv_qx.txt index 83f2a136d3..0298e03434 100644 --- a/docs/man/nutdrv_qx.txt +++ b/docs/man/nutdrv_qx.txt @@ -64,6 +64,9 @@ If you set stayoff in linkman:ups.conf[5] when FSD arises the UPS will call a *s Skip autodetection of the protocol to use and only use the one specified. Supported values: 'bestups', 'hunnox', 'masterguard', 'mecer', 'megatec', 'megatec/old', 'mustek', 'q1', 'voltronic', 'voltronic-qs', 'voltronic-qs-hex' and 'zinto'. + +Run the driver program with the `--help` option to see the exact list of +`protocol` values it would currently recognize. ++ Note that if you end up using the 'q1' protocol, you may want to give a try to the 'mecer', 'megatec' and 'zinto' ones setting the <> (only one, or both). *pollfreq =* 'num':: diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 056130ef50..8f5b01d222 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -39,6 +39,7 @@ */ #include "config.h" +#include #include "main.h" #include "attribute.h" #include "nut_float.h" @@ -2771,20 +2772,45 @@ void upsdrv_shutdown(void) void upsdrv_help(void) { -#ifdef QX_USB - #ifndef TESTING +#ifndef TESTING size_t i; +# ifdef QX_USB + /* Subdrivers have special SOMETHING_command() handling and + * are listed in usbsubdriver[] array (just above in this + * source file). + */ printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: "); - for (i = 0; usbsubdriver[i].name != NULL; i++) { if (i>0) printf(", "); printf("%s", usbsubdriver[i].name); } printf("\n\n"); - #endif -#endif +# endif /* QX_USB*/ + + /* Protocols are the first token from "name" field in + * subdriver_t instances in files like nutdrv_qx_mecer.c + */ + printf("\nAcceptable values for 'protocol' via -x or ups.conf in this driver: "); + for (i = 0; subdriver_list[i] != NULL; i++) { + char subdrv_name[SMALLBUF], *p; + + /* Get rid of subdriver version */ + snprintf(subdrv_name, sizeof(subdrv_name), "%.*s", + (int)strcspn(subdriver_list[i]->name, " "), + subdriver_list[i]->name); + + /* lowercase the (ASCII) string */ + for (p = subdrv_name; *p; ++p) + *p = tolower(*p); + + if (i>0) + printf(", "); + printf("%s", subdrv_name); + } + printf("\n\n"); +#endif /* TESTING */ printf("Read The Fine Manual ('man 8 nutdrv_qx')\n"); } From 3a65d47b747e514c2ab945c8122a805b92bc053f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 18:13:05 +0200 Subject: [PATCH 1070/1232] m4/nut_check_asciidoc.m4, docs/Makefile.am: detect and use ASPELL_FILTER_PATH where available Thanks to https://github.com/msys2/MSYS2-packages/issues/2088 for hints Signed-off-by: Jim Klimov --- docs/Makefile.am | 12 ++++++++++-- m4/nut_check_asciidoc.m4 | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 45b2702022..cd49db4b31 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -48,6 +48,7 @@ ALL_TXT_SRC = nut-names.txt daisychain.txt \ $(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt \ release-notes.txt ChangeLog.txt solaris-usb.txt +ASPELL_FILTER_PATH = @ASPELL_FILTER_PATH@ NUT_SPELL_DICT = nut.dict EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ $(CABLES_IMAGES) $(NUT_SPELL_DICT) \ @@ -385,6 +386,13 @@ SPELLCHECK_ENV_DEBUG = no ASPELL_NUT_COMMON_ARGS = -p $(abs_srcdir)/$(NUT_SPELL_DICT) ASPELL_NUT_COMMON_ARGS += -d en --lang=en --ignore-accents ASPELL_NUT_COMMON_ARGS += --encoding=utf-8 +# Note: If there is a need to use filter path (e.g. in mingw/msys2 builds), +# it must be before --mode=tex (-t) option! +ASPELL_NUT_TEXMODE_ARGS = +if HAVE_ASPELL_FILTER_PATH +ASPELL_NUT_TEXMODE_ARGS += --filter-path="$(ASPELL_FILTER_PATH)" +endif HAVE_ASPELL_FILTER_PATH +ASPELL_NUT_TEXMODE_ARGS += -t ASPELL_ENV_LANG = en.UTF-8 ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$) @@ -402,7 +410,7 @@ $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_DIR)/$(SPELLC @LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ rm -f "$@" || true ; \ echo " ASPELL Spell checking on $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"; \ - OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a -t $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"`" \ + OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"`" \ && { if test -n "$$OUT" ; then OUT="`echo "$$OUT" | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' `" ; fi; \ test -z "$$OUT" ; } \ || { RES=$$? ; \ @@ -419,7 +427,7 @@ spellcheck: LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; \ $(ASPELL) --help || true; \ dpkg -l |grep -i aspell || true ; \ - echo "ASPELL automatic execution line is : ( sed 's,^\(.*\)$$, \1,' < docfile.txt | $(ASPELL) -a -t $(ASPELL_NUT_COMMON_ARGS) | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' )" ; \ + echo "ASPELL automatic execution line is : ( sed 's,^\(.*\)$$, \1,' < docfile.txt | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' )" ; \ echo "ASPELL proceeding to spellchecking job..."; \ else true; fi @FAILED="" ; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ diff --git a/m4/nut_check_asciidoc.m4 b/m4/nut_check_asciidoc.m4 index b83381e50c..d4113ed326 100644 --- a/m4/nut_check_asciidoc.m4 +++ b/m4/nut_check_asciidoc.m4 @@ -80,6 +80,41 @@ if test -z "${nut_have_asciidoc_seen}"; then AC_PATH_PROGS([ASPELL], [aspell]) AM_CONDITIONAL([HAVE_ASPELL], [test -n "$ASPELL"]) + dnl Some builds of aspell (e.g. in mingw) claim they do not know mode "tex" + dnl even though they can list it as a built-in filter and files exist. + dnl It seems that specifying the path helps in those cases. + ASPELL_FILTER_PATH="none" + if test -n "${ASPELL}" ; then + dnl # e.g.: @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.8) + AC_MSG_CHECKING([for aspell version]) + ASPELL_VERSION="`LANG=C LC_ALL=C ${ASPELL} --version 2>/dev/null | sed -e 's,^.*@<:@Aa@:>@spell \(@<:@0-9.@:>@*\),\1,' -e 's,@<:@^0-9.@:>@.*,,'`" || ASPELL_VERSION="none" + AC_MSG_RESULT([${ASPELL_VERSION}]) + + ASPELL_VERSION_MINMAJ="`echo "${ASPELL_VERSION}" | sed 's,\.@<:@0-9@:>@@<:@0-9@:>@*$,,'`" + + AC_MSG_CHECKING([for aspell filtering resources directory]) + ASPELL_BINDIR="`dirname "$ASPELL"`" + if test -d "${ASPELL_BINDIR}/../lib" ; then + if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" ; then + ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" && pwd`" \ + || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" + else + if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" ; then + ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ + || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" + else + if test -d "${ASPELL_BINDIR}/../lib/aspell" ; then + ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell" && pwd`" \ + || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell" + fi + fi + fi + fi + AC_MSG_RESULT([${ASPELL_FILTER_PATH}]) + fi + AM_CONDITIONAL([HAVE_ASPELL_FILTER_PATH], [test -d "$ASPELL_FILTER_PATH"]) + AC_SUBST(ASPELL_FILTER_PATH) + dnl Note that a common "nut_have_asciidoc" variable is in fact a flag dnl that we have several tools needed for the documentation generation dnl TODO? Rename the script variable and makefile flags to reflect this? From c64f61e120c67dddfb0a4d201783925a6db191a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 18 Sep 2023 20:58:48 +0200 Subject: [PATCH 1071/1232] GitIgnore leftover conf1234.file patterns Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1c45b320d6..8d027bcec9 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ Makefile.in /configure /config.nut_report_feature.log* /conf??????/ +/conf??*.file /dir.??????/ /dir?.???????/ /configure-test*/ From f1e426574198c69a200bb9c42849aaf51cdce922 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 09:53:10 +0200 Subject: [PATCH 1072/1232] m4/nut_check_asciidoc.m4, docs/Makefile.am: cater to different ways of packaging aspell with ASPELL_FILTER_TEX_PATH [#2065] Signed-off-by: Jim Klimov --- docs/Makefile.am | 6 +++--- m4/nut_check_asciidoc.m4 | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index cd49db4b31..09cd518e07 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -389,9 +389,9 @@ ASPELL_NUT_COMMON_ARGS += --encoding=utf-8 # Note: If there is a need to use filter path (e.g. in mingw/msys2 builds), # it must be before --mode=tex (-t) option! ASPELL_NUT_TEXMODE_ARGS = -if HAVE_ASPELL_FILTER_PATH -ASPELL_NUT_TEXMODE_ARGS += --filter-path="$(ASPELL_FILTER_PATH)" -endif HAVE_ASPELL_FILTER_PATH +if HAVE_ASPELL_FILTER_TEX_PATH +ASPELL_NUT_TEXMODE_ARGS += --filter-path="$(ASPELL_FILTER_TEX_PATH)" +endif HAVE_ASPELL_FILTER_TEX_PATH ASPELL_NUT_TEXMODE_ARGS += -t ASPELL_ENV_LANG = en.UTF-8 ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$) diff --git a/m4/nut_check_asciidoc.m4 b/m4/nut_check_asciidoc.m4 index d4113ed326..6ec7927597 100644 --- a/m4/nut_check_asciidoc.m4 +++ b/m4/nut_check_asciidoc.m4 @@ -84,6 +84,9 @@ if test -z "${nut_have_asciidoc_seen}"; then dnl even though they can list it as a built-in filter and files exist. dnl It seems that specifying the path helps in those cases. ASPELL_FILTER_PATH="none" + dnl Location of "tex.amf" may be shifted, especially if binary filters + dnl are involved (happens in some platform packages but not others). + ASPELL_FILTER_TEX_PATH="none" if test -n "${ASPELL}" ; then dnl # e.g.: @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.8) AC_MSG_CHECKING([for aspell version]) @@ -111,9 +114,20 @@ if test -z "${nut_have_asciidoc_seen}"; then fi fi AC_MSG_RESULT([${ASPELL_FILTER_PATH}]) + + AC_MSG_CHECKING([for aspell "tex" filtering resources directory]) + if test -d "${ASPELL_FILTER_PATH}" ; then + ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_PATH}" -name "tex.amf"`" \ + && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ + && test -d "${ASPELL_FILTER_TEX_PATH}" \ + || ASPELL_FILTER_TEX_PATH="none" + fi + AC_MSG_RESULT([${ASPELL_FILTER_TEX_PATH}]) fi AM_CONDITIONAL([HAVE_ASPELL_FILTER_PATH], [test -d "$ASPELL_FILTER_PATH"]) AC_SUBST(ASPELL_FILTER_PATH) + AM_CONDITIONAL([HAVE_ASPELL_FILTER_TEX_PATH], [test -d "$ASPELL_FILTER_TEX_PATH"]) + AC_SUBST(ASPELL_FILTER_TEX_PATH) dnl Note that a common "nut_have_asciidoc" variable is in fact a flag dnl that we have several tools needed for the documentation generation From c45945a320fec4699082a1f6647f099d1ba291bd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 10:11:13 +0200 Subject: [PATCH 1073/1232] docs/man/nut_usb_addvars.txt: clarify where "busport" can be verified in the OS [#2043] Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 3 ++- docs/nut.dict | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index b96b252d8d..10479e7697 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -74,7 +74,8 @@ re-boots or device re-plugging. If supported by the hardware, OS and libusb on the particular deployment, this option should allow to specify physical port numbers on an USB hub, rather than logical `device` enumeration values, and in turn -- this should -be less volatile across reboots or re-plugging. +be less volatile across reboots or re-plugging. The value may be seen in +the USB topology output of `lsusb -tv` on systems with that tool, for example. + NOTE: this option is not practically supported by some NUT builds (it should be ignored with a warning then), and not by all systems diff --git a/docs/nut.dict b/docs/nut.dict index af07d51f3c..c34d52d08c 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3230 utf-8 +personal_ws-1.1 en 3231 utf-8 AAS ABI ACFAIL @@ -292,10 +292,10 @@ Dharm DiSplay Diehl Dietze -Disassembly Digitus Digys Dimitris +Disassembly Dly Dmitry DocBook @@ -2998,6 +2998,7 @@ ttymode ttyp tuple turnon +tv tw tx txg From d1316e47395648ac45832a90e9bf19e0a6163945 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 09:05:04 +0000 Subject: [PATCH 1074/1232] m4/nut_check_asciidoc.m4: if there is no "tex.amf", do not yield a useless ASPELL_FILTER_TEX_PATH (e.g. ".") [#2065] Signed-off-by: Jim Klimov --- m4/nut_check_asciidoc.m4 | 1 + 1 file changed, 1 insertion(+) diff --git a/m4/nut_check_asciidoc.m4 b/m4/nut_check_asciidoc.m4 index 6ec7927597..fcc714eb24 100644 --- a/m4/nut_check_asciidoc.m4 +++ b/m4/nut_check_asciidoc.m4 @@ -118,6 +118,7 @@ if test -z "${nut_have_asciidoc_seen}"; then AC_MSG_CHECKING([for aspell "tex" filtering resources directory]) if test -d "${ASPELL_FILTER_PATH}" ; then ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_PATH}" -name "tex.amf"`" \ + && test x"${ASPELL_FILTER_TEX_PATH}" != x \ && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ && test -d "${ASPELL_FILTER_TEX_PATH}" \ || ASPELL_FILTER_TEX_PATH="none" From 1d76e76fc1ed8c3aa2a4e2371c430a5f17f303f8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 10:20:30 +0200 Subject: [PATCH 1075/1232] appveyor.yml: enable spellchecks [#2065] Signed-off-by: Jim Klimov --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 20b9bbe9ec..1ab71e3f99 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -89,7 +89,10 @@ test_script: set CHERE_INVOKING=yes REM Start a 64 bit Mingw environment: set MSYSTEM=MINGW64 + REM Start Mingw-based integration and unit checks: C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" make -s check' + REM Start a Mingw-based documentation spellcheck: + C:\msys64\usr\bin\bash -lc 'date -u; PATH="/mingw64/bin:$PATH" make -s -j 4 spellcheck' after_test: From 29409bafa755a1051e63a742176914c695210204 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 09:16:47 +0000 Subject: [PATCH 1076/1232] m4/nut_check_asciidoc.m4: consider a separate ASPELL_FILTER_SHARE_PATH [#2065] Signed-off-by: Jim Klimov --- m4/nut_check_asciidoc.m4 | 61 +++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/m4/nut_check_asciidoc.m4 b/m4/nut_check_asciidoc.m4 index fcc714eb24..2b7cc9bdd9 100644 --- a/m4/nut_check_asciidoc.m4 +++ b/m4/nut_check_asciidoc.m4 @@ -83,7 +83,8 @@ if test -z "${nut_have_asciidoc_seen}"; then dnl Some builds of aspell (e.g. in mingw) claim they do not know mode "tex" dnl even though they can list it as a built-in filter and files exist. dnl It seems that specifying the path helps in those cases. - ASPELL_FILTER_PATH="none" + ASPELL_FILTER_LIB_PATH="none" + ASPELL_FILTER_SHARE_PATH="none" dnl Location of "tex.amf" may be shifted, especially if binary filters dnl are involved (happens in some platform packages but not others). ASPELL_FILTER_TEX_PATH="none" @@ -95,38 +96,72 @@ if test -z "${nut_have_asciidoc_seen}"; then ASPELL_VERSION_MINMAJ="`echo "${ASPELL_VERSION}" | sed 's,\.@<:@0-9@:>@@<:@0-9@:>@*$,,'`" - AC_MSG_CHECKING([for aspell filtering resources directory]) + AC_MSG_CHECKING([for aspell "lib" filtering resources directory]) ASPELL_BINDIR="`dirname "$ASPELL"`" if test -d "${ASPELL_BINDIR}/../lib" ; then if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" ; then - ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" && pwd`" \ - || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" else if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" ; then - ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ - || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" else if test -d "${ASPELL_BINDIR}/../lib/aspell" ; then - ASPELL_FILTER_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell" && pwd`" \ - || ASPELL_FILTER_PATH="${ASPELL_BINDIR}/../lib/aspell" + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell" fi fi fi fi - AC_MSG_RESULT([${ASPELL_FILTER_PATH}]) + AC_MSG_RESULT([${ASPELL_FILTER_LIB_PATH}]) + + AC_MSG_CHECKING([for aspell "share" filtering resources directory]) + ASPELL_BINDIR="`dirname "$ASPELL"`" + if test -d "${ASPELL_BINDIR}/../share" ; then + if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" + else + if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" + else + if test -d "${ASPELL_BINDIR}/../share/aspell" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell" + fi + fi + fi + fi + AC_MSG_RESULT([${ASPELL_FILTER_SHARE_PATH}]) AC_MSG_CHECKING([for aspell "tex" filtering resources directory]) - if test -d "${ASPELL_FILTER_PATH}" ; then - ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_PATH}" -name "tex.amf"`" \ + dnl # May be in a platform-dependent subdir (e.g. Debian Linux) + dnl # or not (e.g. MinGW/MSYS2, OpenIndiana): + if test -d "${ASPELL_FILTER_LIB_PATH}" ; then + ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_LIB_PATH}" -name "tex.amf"`" \ && test x"${ASPELL_FILTER_TEX_PATH}" != x \ && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ && test -d "${ASPELL_FILTER_TEX_PATH}" \ || ASPELL_FILTER_TEX_PATH="none" fi + dnl # Fallback (e.g. on FreeBSD): + if test x"${ASPELL_FILTER_TEX_PATH}" = xnone \ + && test -d "${ASPELL_FILTER_SHARE_PATH}" ; then + ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_SHARE_PATH}" -name "tex.amf"`" \ + && test x"${ASPELL_FILTER_TEX_PATH}" != x \ + && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ + && test -d "${ASPELL_FILTER_TEX_PATH}" \ + || ASPELL_FILTER_TEX_PATH="none" + fi + AC_MSG_RESULT([${ASPELL_FILTER_TEX_PATH}]) fi - AM_CONDITIONAL([HAVE_ASPELL_FILTER_PATH], [test -d "$ASPELL_FILTER_PATH"]) - AC_SUBST(ASPELL_FILTER_PATH) + AM_CONDITIONAL([HAVE_ASPELL_FILTER_LIB_PATH], [test -d "$ASPELL_FILTER_LIB_PATH"]) + AC_SUBST(ASPELL_FILTER_LIB_PATH) + AM_CONDITIONAL([HAVE_ASPELL_FILTER_SHARE_PATH], [test -d "$ASPELL_FILTER_SHARE_PATH"]) + AC_SUBST(ASPELL_FILTER_SHARE_PATH) AM_CONDITIONAL([HAVE_ASPELL_FILTER_TEX_PATH], [test -d "$ASPELL_FILTER_TEX_PATH"]) AC_SUBST(ASPELL_FILTER_TEX_PATH) From 0952b0bdab6c03e119af1319240d976e00ff05a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 09:57:08 +0000 Subject: [PATCH 1077/1232] configure.ac, m4/nut_check_asciidoc.m4, m4/nut_check_aspell.m4: externalize detection of aspell tool and ability Signed-off-by: Jim Klimov --- configure.ac | 1 + m4/nut_check_asciidoc.m4 | 89 ---------------------------- m4/nut_check_aspell.m4 | 124 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 89 deletions(-) create mode 100644 m4/nut_check_aspell.m4 diff --git a/configure.ac b/configure.ac index f7353f286d..198f909399 100644 --- a/configure.ac +++ b/configure.ac @@ -2362,6 +2362,7 @@ dnl Always check for AsciiDoc prerequisites, since even if --with-doc dnl is set to 'no', we may still want to build some doc targets manually dnl (so enable the Makefile recipes for those targets if tools are available) NUT_CHECK_ASCIIDOC +NUT_CHECK_ASPELL NUT_REPORT_FEATURE([build and install documentation], [${nut_with_doc}], [], [WITH_ASCIIDOC], [Define to enable Asciidoc support]) diff --git a/m4/nut_check_asciidoc.m4 b/m4/nut_check_asciidoc.m4 index 2b7cc9bdd9..6ae8e20236 100644 --- a/m4/nut_check_asciidoc.m4 +++ b/m4/nut_check_asciidoc.m4 @@ -76,95 +76,6 @@ if test -z "${nut_have_asciidoc_seen}"; then AC_PATH_PROGS([SOURCE_HIGHLIGHT], [source-highlight]) AM_CONDITIONAL([HAVE_SOURCE_HIGHLIGHT], [test -n "$SOURCE_HIGHLIGHT"]) - dnl check for spell checking deps - AC_PATH_PROGS([ASPELL], [aspell]) - AM_CONDITIONAL([HAVE_ASPELL], [test -n "$ASPELL"]) - - dnl Some builds of aspell (e.g. in mingw) claim they do not know mode "tex" - dnl even though they can list it as a built-in filter and files exist. - dnl It seems that specifying the path helps in those cases. - ASPELL_FILTER_LIB_PATH="none" - ASPELL_FILTER_SHARE_PATH="none" - dnl Location of "tex.amf" may be shifted, especially if binary filters - dnl are involved (happens in some platform packages but not others). - ASPELL_FILTER_TEX_PATH="none" - if test -n "${ASPELL}" ; then - dnl # e.g.: @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.8) - AC_MSG_CHECKING([for aspell version]) - ASPELL_VERSION="`LANG=C LC_ALL=C ${ASPELL} --version 2>/dev/null | sed -e 's,^.*@<:@Aa@:>@spell \(@<:@0-9.@:>@*\),\1,' -e 's,@<:@^0-9.@:>@.*,,'`" || ASPELL_VERSION="none" - AC_MSG_RESULT([${ASPELL_VERSION}]) - - ASPELL_VERSION_MINMAJ="`echo "${ASPELL_VERSION}" | sed 's,\.@<:@0-9@:>@@<:@0-9@:>@*$,,'`" - - AC_MSG_CHECKING([for aspell "lib" filtering resources directory]) - ASPELL_BINDIR="`dirname "$ASPELL"`" - if test -d "${ASPELL_BINDIR}/../lib" ; then - if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" ; then - ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" && pwd`" \ - || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" - else - if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" ; then - ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ - || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" - else - if test -d "${ASPELL_BINDIR}/../lib/aspell" ; then - ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell" && pwd`" \ - || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell" - fi - fi - fi - fi - AC_MSG_RESULT([${ASPELL_FILTER_LIB_PATH}]) - - AC_MSG_CHECKING([for aspell "share" filtering resources directory]) - ASPELL_BINDIR="`dirname "$ASPELL"`" - if test -d "${ASPELL_BINDIR}/../share" ; then - if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" ; then - ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" && pwd`" \ - || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" - else - if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" ; then - ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ - || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" - else - if test -d "${ASPELL_BINDIR}/../share/aspell" ; then - ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell" && pwd`" \ - || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell" - fi - fi - fi - fi - AC_MSG_RESULT([${ASPELL_FILTER_SHARE_PATH}]) - - AC_MSG_CHECKING([for aspell "tex" filtering resources directory]) - dnl # May be in a platform-dependent subdir (e.g. Debian Linux) - dnl # or not (e.g. MinGW/MSYS2, OpenIndiana): - if test -d "${ASPELL_FILTER_LIB_PATH}" ; then - ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_LIB_PATH}" -name "tex.amf"`" \ - && test x"${ASPELL_FILTER_TEX_PATH}" != x \ - && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ - && test -d "${ASPELL_FILTER_TEX_PATH}" \ - || ASPELL_FILTER_TEX_PATH="none" - fi - dnl # Fallback (e.g. on FreeBSD): - if test x"${ASPELL_FILTER_TEX_PATH}" = xnone \ - && test -d "${ASPELL_FILTER_SHARE_PATH}" ; then - ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_SHARE_PATH}" -name "tex.amf"`" \ - && test x"${ASPELL_FILTER_TEX_PATH}" != x \ - && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ - && test -d "${ASPELL_FILTER_TEX_PATH}" \ - || ASPELL_FILTER_TEX_PATH="none" - fi - - AC_MSG_RESULT([${ASPELL_FILTER_TEX_PATH}]) - fi - AM_CONDITIONAL([HAVE_ASPELL_FILTER_LIB_PATH], [test -d "$ASPELL_FILTER_LIB_PATH"]) - AC_SUBST(ASPELL_FILTER_LIB_PATH) - AM_CONDITIONAL([HAVE_ASPELL_FILTER_SHARE_PATH], [test -d "$ASPELL_FILTER_SHARE_PATH"]) - AC_SUBST(ASPELL_FILTER_SHARE_PATH) - AM_CONDITIONAL([HAVE_ASPELL_FILTER_TEX_PATH], [test -d "$ASPELL_FILTER_TEX_PATH"]) - AC_SUBST(ASPELL_FILTER_TEX_PATH) - dnl Note that a common "nut_have_asciidoc" variable is in fact a flag dnl that we have several tools needed for the documentation generation dnl TODO? Rename the script variable and makefile flags to reflect this? diff --git a/m4/nut_check_aspell.m4 b/m4/nut_check_aspell.m4 new file mode 100644 index 0000000000..4fb7feaa9f --- /dev/null +++ b/m4/nut_check_aspell.m4 @@ -0,0 +1,124 @@ +dnl Check for tools used in spell-checking of documentation source files. +dnl On success, set nut_have_aspell="yes" (meaning we can do at least some +dnl documentation checks) and lots of automake macros and configure vars. +dnl On failure, set nut_have_aspell="no" (meaning we can't run the checks). +dnl This macro can be run multiple times, but will do the checking only once. + +AC_DEFUN([NUT_CHECK_ASPELL], +[ +if test -z "${nut_have_aspell_seen}"; then + nut_have_aspell_seen=yes + + dnl # Note: this is just a known-working version on NUT CI platforms: + dnl # Legacy baselines (CentOS 7, OpenBSD 6.5): + dnl # @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.6.1) + dnl # More recent distros (as of 2022-2023): + dnl # @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.8) + ASPELL_MIN_VERSION="0.60.6" + + dnl check for spell checking deps + AC_PATH_PROGS([ASPELL], [aspell]) + + dnl Some builds of aspell (e.g. in mingw) claim they do not know mode "tex" + dnl even though they can list it as a built-in filter and files exist. + dnl It seems that specifying the path helps in those cases. + ASPELL_FILTER_LIB_PATH="none" + ASPELL_FILTER_SHARE_PATH="none" + dnl Location of "tex.amf" may be shifted, especially if binary filters + dnl are involved (happens in some platform packages but not others). + ASPELL_FILTER_TEX_PATH="none" + if test -n "${ASPELL}" ; then + dnl # e.g.: @(#) International Ispell Version 3.1.20 (but really Aspell 0.60.8) + AC_MSG_CHECKING([for aspell version]) + ASPELL_VERSION="`LANG=C LC_ALL=C ${ASPELL} --version 2>/dev/null | sed -e 's,^.*@<:@Aa@:>@spell \(@<:@0-9.@:>@*\),\1,' -e 's,@<:@^0-9.@:>@.*,,'`" || ASPELL_VERSION="none" + AC_MSG_RESULT([${ASPELL_VERSION}]) + + ASPELL_VERSION_MINMAJ="`echo "${ASPELL_VERSION}" | sed 's,\.@<:@0-9@:>@@<:@0-9@:>@*$,,'`" + + AC_MSG_CHECKING([for aspell "lib" filtering resources directory]) + ASPELL_BINDIR="`dirname "$ASPELL"`" + if test -d "${ASPELL_BINDIR}/../lib" ; then + if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" ; then + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION}" + else + if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" ; then + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell-${ASPELL_VERSION_MINMAJ}" + else + if test -d "${ASPELL_BINDIR}/../lib/aspell" ; then + ASPELL_FILTER_LIB_PATH="`cd "${ASPELL_BINDIR}/../lib/aspell" && pwd`" \ + || ASPELL_FILTER_LIB_PATH="${ASPELL_BINDIR}/../lib/aspell" + fi + fi + fi + fi + AC_MSG_RESULT([${ASPELL_FILTER_LIB_PATH}]) + + AC_MSG_CHECKING([for aspell "share" filtering resources directory]) + ASPELL_BINDIR="`dirname "$ASPELL"`" + if test -d "${ASPELL_BINDIR}/../share" ; then + if test x"${ASPELL_VERSION}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION}" + else + if test x"${ASPELL_VERSION_MINMAJ}" != x"none" && test -d "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell-${ASPELL_VERSION_MINMAJ}" + else + if test -d "${ASPELL_BINDIR}/../share/aspell" ; then + ASPELL_FILTER_SHARE_PATH="`cd "${ASPELL_BINDIR}/../share/aspell" && pwd`" \ + || ASPELL_FILTER_SHARE_PATH="${ASPELL_BINDIR}/../share/aspell" + fi + fi + fi + fi + AC_MSG_RESULT([${ASPELL_FILTER_SHARE_PATH}]) + + AC_MSG_CHECKING([for aspell "tex" filtering resources directory]) + dnl # May be in a platform-dependent subdir (e.g. Debian Linux) + dnl # or not (e.g. MinGW/MSYS2, OpenIndiana): + if test -d "${ASPELL_FILTER_LIB_PATH}" ; then + ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_LIB_PATH}" -name "tex.amf"`" \ + && test x"${ASPELL_FILTER_TEX_PATH}" != x \ + && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ + && test -d "${ASPELL_FILTER_TEX_PATH}" \ + || ASPELL_FILTER_TEX_PATH="none" + fi + dnl # Fallback (e.g. on FreeBSD): + if test x"${ASPELL_FILTER_TEX_PATH}" = xnone \ + && test -d "${ASPELL_FILTER_SHARE_PATH}" ; then + ASPELL_FILTER_TEX_PATH="`find "${ASPELL_FILTER_SHARE_PATH}" -name "tex.amf"`" \ + && test x"${ASPELL_FILTER_TEX_PATH}" != x \ + && ASPELL_FILTER_TEX_PATH="`dirname "${ASPELL_FILTER_TEX_PATH}"`" \ + && test -d "${ASPELL_FILTER_TEX_PATH}" \ + || ASPELL_FILTER_TEX_PATH="none" + fi + + AC_MSG_RESULT([${ASPELL_FILTER_TEX_PATH}]) + fi + AM_CONDITIONAL([HAVE_ASPELL_FILTER_LIB_PATH], [test -d "$ASPELL_FILTER_LIB_PATH"]) + AC_SUBST(ASPELL_FILTER_LIB_PATH) + AM_CONDITIONAL([HAVE_ASPELL_FILTER_SHARE_PATH], [test -d "$ASPELL_FILTER_SHARE_PATH"]) + AC_SUBST(ASPELL_FILTER_SHARE_PATH) + AM_CONDITIONAL([HAVE_ASPELL_FILTER_TEX_PATH], [test -d "$ASPELL_FILTER_TEX_PATH"]) + AC_SUBST(ASPELL_FILTER_TEX_PATH) + + AC_MSG_CHECKING([if aspell version can do our documentation spell checks (minimum required ${ASPELL_MIN_VERSION})]) + AX_COMPARE_VERSION([${ASPELL_VERSION}], [ge], [${ASPELL_MIN_VERSION}], [ + AC_MSG_RESULT(yes) + nut_have_aspell="yes" + ], [ + AC_MSG_RESULT(no) + nut_have_aspell="no" + ]) + + dnl Notes: we also keep HAVE_ASPELL for implicit targets, such as + dnl addition to "make check" target + dnl ### AM_CONDITIONAL([HAVE_ASPELL], [test -n "$ASPELL"]) + AM_CONDITIONAL([HAVE_ASPELL], [test "${nut_have_aspell}" = "yes"]) + + AC_MSG_CHECKING([if we have all the tools mandatory for documentation spell checks]) + AC_MSG_RESULT([${nut_have_aspell}]) +fi +]) From be322e0f7d58d7dcf80e3053dd10a929e6ff401f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 10:08:56 +0000 Subject: [PATCH 1078/1232] configure.ac: introduce --enable-spellcheck to have it as part of "make check" where available [#2067] Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++++ UPGRADING.adoc | 7 ++++++- configure.ac | 26 +++++++++++++++++++++++++- docs/Makefile.am | 7 ++++++- docs/configure.txt | 7 +++++++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b9e7b4495c..c132b8cce5 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -65,6 +65,10 @@ https://github.com/networkupstools/nut/milestone/8 instead. Documentation links rendered in GitHub UI should point to the HTML pages served by a current iteration of the NUT website. [PR #226, PR #669] + - A new `configure --enable-spellcheck` toggle should add spelling checks + to `make check` (by default, if tools are available) to facilitate quicker + acceptance of contributions. [#2067] + - Published a new maintainer GPG key to sign tags and release artifacts, and possibly git commits as well, as part of solution for issue #1410. You can pull it from common OpenPGP servers with the following command: diff --git a/UPGRADING.adoc b/UPGRADING.adoc index ee90a01c8d..3c40e19f8e 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -29,7 +29,12 @@ Changes from 2.8.0 to 2.8.1 - NUT documentation recipes were revised, so many of the text source files were renamed to `*.adoc` pattern. Newly, a `release-notes.pdf` and HTML equivalents are generated. Packages which deliver documentation may need - to update the lists of files to ship. [#1953] + to update the lists of files to ship. [#1953] Developers may be impacted + by new `configure --enable-spellcheck` toggle (should add spelling checks + to `make check` by default, if tools are available) to facilitate quicker + acceptance of contributions. Packaging systems may now want to explicitly + disable it, if it blocks package building (pull requests to update the + `docs/nut.dict` are a better and welcome solution). [#2067] - Several improvements regarding simultaneous support of USB devices that were previously deemed "identical" and so NUT driver instances did not diff --git a/configure.ac b/configure.ac index 198f909399..a499393720 100644 --- a/configure.ac +++ b/configure.ac @@ -2355,6 +2355,31 @@ AC_ARG_ENABLE([check-NIT], AM_CONDITIONAL(WITH_CHECK_NIT, test "${nut_enable_check_NIT}" = "yes") +dnl ---------------------------------------------------------------------- +dnl checks related to --enable-spellcheck + +NUT_CHECK_ASPELL +NUT_ARG_ENABLE([spellcheck], [Run spellcheck among default checks], [auto]) + +AC_MSG_CHECKING(whether to run spellcheck among default make check target) +case "${nut_enable_spellcheck}" in + yes) if test "${nut_have_aspell}" = "no" ; then + AC_MSG_ERROR([Requested to --enable-spellcheck but did not find a good one]) + fi + WITH_SPELLCHECK=yes + ;; + no) WITH_SPELLCHECK=no ;; + auto) if test "${nut_have_aspell}" = "yes" ; then + WITH_SPELLCHECK=yes + else + WITH_SPELLCHECK=no + fi + ;; +esac +AC_MSG_RESULT([${WITH_SPELLCHECK}]) + +AM_CONDITIONAL(WITH_SPELLCHECK, test "${WITH_SPELLCHECK}" = "yes") + dnl ---------------------------------------------------------------------- dnl checks related to --with-doc @@ -2362,7 +2387,6 @@ dnl Always check for AsciiDoc prerequisites, since even if --with-doc dnl is set to 'no', we may still want to build some doc targets manually dnl (so enable the Makefile recipes for those targets if tools are available) NUT_CHECK_ASCIIDOC -NUT_CHECK_ASPELL NUT_REPORT_FEATURE([build and install documentation], [${nut_with_doc}], [], [WITH_ASCIIDOC], [Define to enable Asciidoc support]) diff --git a/docs/Makefile.am b/docs/Makefile.am index 09cd518e07..78ee2aee1e 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -421,7 +421,7 @@ $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_DIR)/$(SPELLC exit $$RES; } ; \ touch "$@" -spellcheck: +spellcheck: @if test "$(SPELLCHECK_ENV_DEBUG)" != no ; then \ echo "ASPELL DEBUG : information about the setup follows:"; \ LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; \ @@ -497,6 +497,11 @@ spellcheck-interactive: echo "to review changes (please DO NOT REMOVE LINES that aspell chose to drop,"; \ echo "because other systems might not know these words in their system dictionaries)"; \ echo "------------------------------------------------------------------------" + +if WITH_SPELLCHECK +check-local: spellcheck +endif WITH_SPELLCHECK + else !HAVE_ASPELL # This rule woulf probably just fail; normally with no ASPELL there are no callers for it */*-spellchecked *-spellchecked: Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) diff --git a/docs/configure.txt b/docs/configure.txt index 91f08ec669..9ff3d2bba9 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -400,6 +400,13 @@ build further projects against NUT (such as wmNUT client and many others). Options for developers ~~~~~~~~~~~~~~~~~~~~~~ + --enable-spellcheck (default: auto) + +Activate recipes for documentation source file spelling checks with `aspell` +tool. Default behavior depends on availability of the tool, so if present -- +it would run for `make check` by default, to facilitate quicker acceptance +of contributions. + --enable-check-NIT (default: no) Add `make check-NIT` to default activity of `make check` to run the From ae4b0058e956bf85010e8e6a8208078ce047020e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 10:33:57 +0000 Subject: [PATCH 1079/1232] configure: fix handling of --enable-cppcheck Signed-off-by: Jim Klimov --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a499393720..0df68d1e8c 100644 --- a/configure.ac +++ b/configure.ac @@ -2315,6 +2315,7 @@ dnl unless desired). NUT_ARG_ENABLE([cppcheck], [Run a cppcheck on the codebase among checks], [no]) NUT_CHECK_CPPCHECK +AC_MSG_CHECKING(whether to run cppcheck among default make check target) case "${nut_enable_cppcheck}" in yes) if test "${nut_have_cppcheck}" = "no" ; then AC_MSG_ERROR([Requested to --enable-cppcheck but did not find a good one]) @@ -2323,12 +2324,13 @@ case "${nut_enable_cppcheck}" in ;; no) WITH_CPPCHECK=no ;; auto) if test "${nut_have_cppcheck}" = "yes" ; then - WITH_CPPCHECK=no + WITH_CPPCHECK=yes else WITH_CPPCHECK=no fi ;; esac +AC_MSG_RESULT([${WITH_CPPCHECK}]) AM_CONDITIONAL(WITH_CPPCHECK, test "${WITH_CPPCHECK}" = "yes") From 1b9e1521a5b183d9fd8793b83e0910d2835b8a69 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 13:06:41 +0000 Subject: [PATCH 1080/1232] Makefile.am: Introduce LICENSE-DCO into the source codebase [#1994] Signed-off-by: Jim Klimov --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 9c0667c88e..c367c904a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ libtool: $(LIBTOOL_DEPS) # by automake. Note that the INSTALL file is (re-)imposed by autotools # runs and is essentially a manual on configure script general usage, so # NUT's actual installation notes have had to use a different filename. -EXTRA_DIST = LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS +EXTRA_DIST = LICENSE-GPL2 LICENSE-GPL3 LICENSE-DCO MAINTAINERS # Since the renaming of documentation to `*.adoc` extension to help IDE # and GitHub UIs to render the source files in a pretty fashion, we need From b2b2f00cee6122249b550f24b63358b5c96938e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 13:10:29 +0000 Subject: [PATCH 1081/1232] docs/Makefile.am: EXTRA_DIST asciidoc-vars.conf [#1953] Signed-off-by: Jim Klimov --- docs/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 78ee2aee1e..36d7084bf0 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -52,7 +52,7 @@ ASPELL_FILTER_PATH = @ASPELL_FILTER_PATH@ NUT_SPELL_DICT = nut.dict EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ $(CABLES_IMAGES) $(NUT_SPELL_DICT) \ - docinfo.xml common.xsl xhtml.xsl chunked.xsl asciidoc.txt + docinfo.xml common.xsl xhtml.xsl chunked.xsl asciidoc.txt asciidoc-vars.conf ASCIIDOC_HTML_SINGLE = user-manual.html \ developer-guide.html \ From b3c684163f69778a35169c93eb83b6bf87e0bda5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 13:27:07 +0000 Subject: [PATCH 1082/1232] */Makefile.am: spellcheck targets: differentiate SPELLCHECK_SRCDIR vs. SPELLCHECK_BUILDDIR [#2067] Signed-off-by: Jim Klimov --- conf/Makefile.am | 8 ++++---- data/Makefile.am | 6 +++--- docs/Makefile.am | 21 +++++++++++---------- docs/man/Makefile.am | 6 +++--- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/conf/Makefile.am b/conf/Makefile.am index 847c2994c5..8adf280071 100644 --- a/conf/Makefile.am +++ b/conf/Makefile.am @@ -21,20 +21,20 @@ SPELLCHECK_SRC = $(dist_sysconf_DATA) \ # NOTE: Due to portability, we do not use a GNU percent-wildcard extension: #%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -# $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ +# $(MAKE) -s -f $(top_builddir)/docs/Makefile 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: - $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ .in.in-spellchecked: - $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ spellcheck spellcheck-interactive spellcheck-sortdict: - $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ MAINTAINERCLEANFILES = Makefile.in .dirstamp diff --git a/data/Makefile.am b/data/Makefile.am index 99098184cb..df4cd1a8d1 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -8,13 +8,13 @@ EXTRA_DIST = evolution500.seq epdu-managed.dev # NOTE: Due to portability, we do not use a GNU percent-wildcard extension: #%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -# $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ +# $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ cmdvartab-spellchecked: cmdvartab Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) - $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ spellcheck spellcheck-interactive spellcheck-sortdict: - $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="cmdvartab" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="cmdvartab" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ MAINTAINERCLEANFILES = Makefile.in .dirstamp CLEANFILES = *.pdf *.html *-spellchecked diff --git a/docs/Makefile.am b/docs/Makefile.am index 36d7084bf0..621f8e322f 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -367,7 +367,8 @@ SPELLCHECK_SRC = $(ALL_TXT_SRC) \ ../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3 ../LICENSE-DCO # Directory SPELLCHECK_SRC files are relative to. Overriden by other Makefiles. -SPELLCHECK_DIR = $(srcdir) +SPELLCHECK_SRCDIR = $(srcdir) +SPELLCHECK_BUILDDIR = $(builddir) # Note: de-facto our documentation is beyond ASCII (at least in names of # international committers). The grep tests below look if the aspell output @@ -406,11 +407,11 @@ ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$) #*-spellchecked */*-spellchecked: $(@:-spellchecked=) $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) # NOTE: This portable rule RELIES on just one SPELLCHECK_SRC defined # at a time, with an outer Makefile caller ensuring the looping: -$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE) $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +$(SPELLCHECK_BUILDDIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE) $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ rm -f "$@" || true ; \ - echo " ASPELL Spell checking on $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"; \ - OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"`" \ + echo " ASPELL Spell checking on $(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)"; \ + OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)"`" \ && { if test -n "$$OUT" ; then OUT="`echo "$$OUT" | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' `" ; fi; \ test -z "$$OUT" ; } \ || { RES=$$? ; \ @@ -433,10 +434,10 @@ spellcheck: @FAILED="" ; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ for docsrc in $(SPELLCHECK_SRC); do \ if test "$(SPELLCHECK_ENV_DEBUG)" != no ; then \ - echo "ASPELL MAKEFILE DEBUG: Will see from `pwd` if '$(SPELLCHECK_DIR)/$${docsrc}-spellchecked' is up to date" >&2; \ + echo "ASPELL MAKEFILE DEBUG: Will see from `pwd` if '$(SPELLCHECK_SRCDIR)/$${docsrc}-spellchecked' is up to date" >&2; \ else true ; fi ; \ - $(MAKE) -s -f "$(abs_top_builddir)/docs/Makefile" SPELLCHECK_SRC_ONE="$${docsrc}" SPELLCHECK_DIR="$(SPELLCHECK_DIR)" "$(SPELLCHECK_DIR)/$${docsrc}-spellchecked" \ - || FAILED="$$FAILED $(SPELLCHECK_DIR)/$$docsrc"; \ + $(MAKE) -s -f "$(abs_top_builddir)/docs/Makefile" SPELLCHECK_SRC_ONE="$${docsrc}" SPELLCHECK_BUILDDIR="$(SPELLCHECK_BUILDDIR)" SPELLCHECK_SRCDIR="$(SPELLCHECK_SRCDIR)" "$(SPELLCHECK_BUILDDIR)/$${docsrc}-spellchecked" \ + || FAILED="$$FAILED $(SPELLCHECK_SRCDIR)/$$docsrc"; \ done ; \ if test -n "$$FAILED" ; then \ echo "=====================================================================" ; \ @@ -482,9 +483,9 @@ DISTCLEANFILES = $(NUT_SPELL_DICT).bak-pre-sorting .$(NUT_SPELL_DICT).sorted $(N spellcheck-interactive: @FAILED="" ; for docsrc in $(SPELLCHECK_SRC); do \ - echo "Spell checking on $(SPELLCHECK_DIR)/$$docsrc"; \ - LANG=$(ASPELL_ENV_LANG) LC_ALL=$(ASPELL_ENV_LANG) $(ASPELL) check $(ASPELL_NUT_COMMON_ARGS) $(SPELLCHECK_DIR)/$$docsrc || \ - FAILED="$$FAILED $(SPELLCHECK_DIR)/$$docsrc"; \ + echo "Spell checking on $(SPELLCHECK_SRCDIR)/$$docsrc"; \ + LANG=$(ASPELL_ENV_LANG) LC_ALL=$(ASPELL_ENV_LANG) $(ASPELL) check $(ASPELL_NUT_COMMON_ARGS) $(SPELLCHECK_SRCDIR)/$$docsrc || \ + FAILED="$$FAILED $(SPELLCHECK_SRCDIR)/$$docsrc"; \ done ; \ if test -n "$$FAILED" ; then \ echo "FAILED interactive spellcheck for the following sources (relative to `pwd`): $$FAILED" >&2 ; \ diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 65a316beae..9944c46560 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -1071,16 +1071,16 @@ endif !HAVE_ASCIIDOC # NOTE: Due to portability, we do not use a GNU percent-wildcard extension: #%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -# $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ +# $(MAKE) -s -f $(top_builddir)/docs/Makefile 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: - $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ spellcheck spellcheck-interactive spellcheck-sortdict: - $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SRC_ALL_PAGES)" SPELLCHECK_DIR="$(srcdir)" $@ + $(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SRC_ALL_PAGES)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ MAINTAINERCLEANFILES = Makefile.in .dirstamp From 5332dba08f641e9423a94d80cb20958c614aa854 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 15:51:27 +0200 Subject: [PATCH 1083/1232] docs/Makefile.am: fix ChangeLog.adoc preparation for OpenBSD make [#1953] Signed-off-by: Jim Klimov --- docs/Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 621f8e322f..4f234e6a54 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -188,13 +188,13 @@ $(top_builddir)/ChangeLog: @echo " DOC-CHANGELOG-GENERATE $@" \ && cd $(top_builddir) && $(MAKE) $(AM_FLAGS) $(@F) -# BSD Make dislikes the path resolution here and does not always -# populate "$<", but it has a "$?" for "list of dependencies that -# are newer than the target". For more details see -# https://man.freebsd.org/cgi/man.cgi +# BSD Make dislikes the path resolution here and does not always populate "$<" +# (and claims why: "Using $< in a non-suffix rule context is a GNUmake idiom"), +# but it has a "$?" for "list of dependencies that are newer than the target". +# For more details see https://man.freebsd.org/cgi/man.cgi $(top_builddir)/ChangeLog.adoc: $(top_builddir)/ChangeLog - @INPUT="$<"; \ - test -n "$${INPUT}" || INPUT="$?" ; \ + @INPUT="$?"; \ + test -n "$${INPUT}" || INPUT="$$(top_builddir)/ChangeLog" ; \ test -n "$${INPUT}" && test -n "$@" && test -s "$${INPUT}" \ || { \ MSG="FAILED to resolve input or output filename with this make implementation, or input was not generated!"; \ From ebd4c4b26a32e3ea6c972e7eb64250c0bef42e3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 22:44:55 +0200 Subject: [PATCH 1084/1232] docs/developers.txt, docs/nut.dict: clarify that NUT_UNUSED_VARIABLE goes after variable declarations, add chapter headings, revise some text [#2056] Signed-off-by: Jim Klimov --- docs/developers.txt | 37 +++++++++++++++++++++++++++++++++++-- docs/nut.dict | 3 ++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/docs/developers.txt b/docs/developers.txt index 9510288428..722d1699ea 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -101,6 +101,9 @@ Portability Avoid things that will break on other systems. All the world is not an x86 Linux box. +C comments +~~~~~~~~~~ + There are still older systems out there that don't do C++ style comments. -------------------------------------- @@ -108,6 +111,9 @@ There are still older systems out there that don't do C++ style comments. // Not like this. -------------------------------------- +Variable declarations go on top +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Newer versions of gcc allow you to declare a variable inside a function after code, somewhat like the way C++ operates, like this: @@ -123,8 +129,28 @@ function do_stuff(void) ------------------------------------------------------------------------------- While this will compile and run on these newer versions, it will fail -miserably for anyone on an older system. That means you must not use -it. `gcc` only warns about this with `-pedantic` flag. +miserably for anyone on an older system. That means you must not use it. + +Note that `gcc` only warns about this with `-pedantic` flag, and `clang` +with a `-Weverything` (possibly `-Wextra`) flag, which can be enabled by +developers with `configure --enable-warnings=...` option values (and made +fatal with `configure --enable-Werror`), to ensure non-regression of code +quality. It was reported that `clang-16` with such options does complain +about non-portability to older C language revisions even if explicitly +building for a newer revision. + +Please note that for the purposes of legacy-compatible variable declarations +(on top of their scopes), a `NUT_UNUSED_VARIABLE(varname)` counts as code and +should be used just below the declarations. Initial assignments to variables +(also as return values of methods) may generally happen as part of their +declarations. + +You can use scoping (e.g. `do { ... } while (0);`) where it makes sense +to constrain visibility of temporary variables, such as in `switch/case` +blocks. + +Variable declaration in loop block syntax +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Another feature that does not work on some compilers (e.g. conforming to "ANSI C"/C89/C90 standard) is initial variable declaration inside a @@ -140,6 +166,9 @@ function do_stuff(void) } -------------------------------------------------------------------------------- +Other hints +~~~~~~~~~~~ + TIP: At this point NUT is expected to work correctly when built with a C99 (or rather GNU99 on many systems) or newer standard. @@ -981,6 +1010,10 @@ body of the function (or an `#ifdef` branch of its code) using the `NUT_UNUSED_VARIABLE(varname)` as a routine call inside a function body, referring to the macro defined in `common.h`. +Please note that for the purposes of legacy-compatible variable declarations +(on top of their scopes), `NUT_UNUSED_VARIABLE(varname)` counts as code and +should happen below the declarations. + To display in a rough example: ------------------------------------------------------------------------------- diff --git a/docs/nut.dict b/docs/nut.dict index c34d52d08c..3d0701ba42 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3231 utf-8 +personal_ws-1.1 en 3232 utf-8 AAS ABI ACFAIL @@ -1396,6 +1396,7 @@ WantedBy WatchdogSec WebFreak Werror +Weverything Wextra WhizBang Wikipedia From cbce8c36fa79343b22f22fe822c223aeec4ef362 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 22:50:51 +0200 Subject: [PATCH 1085/1232] drivers/usbhid-ups.c: fix visibility of vars used only in builds with HAVE_LIBREGEX [#1369] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 800abe3bbe..c078354805 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -538,9 +538,10 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { /* Pick up the subdriver name if set explicitly */ if (subdrv) { - int res, i, flag_HAVE_LIBREGEX = 0; - size_t len; + int i, flag_HAVE_LIBREGEX = 0; #if (defined HAVE_LIBREGEX && HAVE_LIBREGEX) + int res; + size_t len; regex_t *regex_ptr = NULL; flag_HAVE_LIBREGEX = 1; #endif @@ -610,7 +611,6 @@ static subdriver_t *match_function_subdriver_name(int fatal_mismatch) { regex_ptr = NULL; } } - #endif /* HAVE_LIBREGEX */ if (fatal_mismatch) { From cb5e92cccdb30c10d11546a9a4bb92ca28831b9f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 19 Sep 2023 22:59:00 +0200 Subject: [PATCH 1086/1232] drivers/usb-common.c: make sure to have settings like HAVE_LIBREGEX visible when processing other headers [#1369] Signed-off-by: Jim Klimov --- drivers/usb-common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb-common.c b/drivers/usb-common.c index ccdb104a59..6c10860ef8 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" /* must be first */ #include "common.h" #include "usb-common.h" From 2f08b9b436fa82be9b4f457938a32ca8c145646f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 20 Sep 2023 15:48:57 +0200 Subject: [PATCH 1087/1232] docs/nut.dict: update dictionary for nut-website changes Signed-off-by: Jim Klimov --- docs/nut.dict | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 3d0701ba42..46ee7ef0fc 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3232 utf-8 +personal_ws-1.1 en 3238 utf-8 AAS ABI ACFAIL @@ -312,6 +312,7 @@ EMI EMP ENDFOR ENV +EOC EOF EOLed EPEL @@ -1075,6 +1076,7 @@ Rodríguez Rouben Rozman Rucelf +RuntimeWarning RxD RxHs Ryabov @@ -1286,6 +1288,7 @@ ToddGreenfield Tomek TopGuard Toth +Traceback TrackingID TrackingResult Tripp @@ -1729,6 +1732,7 @@ collectd colspan command's commandlen +commentsMap committer compat compilerPath @@ -2391,6 +2395,7 @@ monuser morbo mozilla msec +msg msgfmt msi msvcrt @@ -2428,6 +2433,7 @@ nb nbr nd ndcv +nds nearlowbattery netcat netclient From 692474b8727acba864a6838bf5a174030381859b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 20 Sep 2023 10:57:49 +0200 Subject: [PATCH 1088/1232] ci_build.sh: make sure our MAKE envvar is defined and not empty - in all cases [networkupstools/jenkins-dynamatrix#24] Signed-off-by: Jim Klimov --- ci_build.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 52d9ff75ba..57a9b11c87 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -446,6 +446,18 @@ if [ -z "${PKG_CONFIG-}" ]; then PKG_CONFIG="pkg-config" fi +# It seems sometimes we get blanks from CI +if [ -z "`echo "${MAKE-}" | tr -d ' '`" ] ; then + if (command -v gmake) >/dev/null 2>/dev/null ; then + # GNU make processes quiet mode better, which helps with this use-case + MAKE=gmake + else + # Use system default, there should be one + MAKE=make + fi + export MAKE +fi + # Would hold full path to the CONFIGURE_SCRIPT="${SCRIPTDIR}/${CONFIGURE_SCRIPT_FILENAME}" CONFIGURE_SCRIPT="" autogen_get_CONFIGURE_SCRIPT() { @@ -726,16 +738,6 @@ fi if [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] && [ -z "$BUILD_TYPE" ] ; then # Note: this is a little hack to reduce typing # and scrolling in (docs) developer iterations. - if [ -z "${MAKE-}" ] ; then - if (command -v gmake) >/dev/null 2>/dev/null ; then - # GNU make processes quiet mode better, which helps with this use-case - MAKE=gmake - else - # Use system default, there should be one - MAKE=make - fi - export MAKE - fi case "$CI_OS_NAME" in windows-msys2) # https://github.com/msys2/MSYS2-packages/issues/2088 From 482bd19f54466d265dda22b6c446edd3b11e187b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 20 Sep 2023 13:02:59 +0200 Subject: [PATCH 1089/1232] ci_build.sh: --disable-spellcheck in many default BUILD_TYPE=... scenarios geared towards binary builds and checks (do not waste time on aspell in matrix checking loops) [#2065] Signed-off-by: Jim Klimov --- ci_build.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci_build.sh b/ci_build.sh index 57a9b11c87..503345a891 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1080,12 +1080,14 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp case "$BUILD_TYPE" in "default-nodoc") CONFIG_OPTS+=("--with-doc=no") + CONFIG_OPTS+=("--disable-spellcheck") DO_DISTCHECK=no ;; "default-spellcheck"|"default-shellcheck") CONFIG_OPTS+=("--with-all=no") CONFIG_OPTS+=("--with-libltdl=no") CONFIG_OPTS+=("--with-doc=man=skip") + CONFIG_OPTS+=("--enable-spellcheck") #TBD# CONFIG_OPTS+=("--with-shellcheck=yes") DO_DISTCHECK=no ;; @@ -1139,6 +1141,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # Do not build the docs as we are interested in binary code CONFIG_OPTS+=("--with-doc=skip") + CONFIG_OPTS+=("--disable-spellcheck") # Enable as many binaries to build as current worker setup allows CONFIG_OPTS+=("--with-all=auto") @@ -1164,6 +1167,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp "default-alldrv") # Do not build the docs and make possible a distcheck below CONFIG_OPTS+=("--with-doc=skip") + CONFIG_OPTS+=("--disable-spellcheck") if [ "${CANBUILD_DRIVERS_ALL-}" = no ]; then echo "WARNING: Build agent says it can't build 'all' driver types; will ask for what we can build" >&2 if [ "$DO_DISTCHECK" != no ]; then @@ -1190,6 +1194,7 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp "default"|"default-tgt:"*|*) # Do not build the docs and tell distcheck it is okay CONFIG_OPTS+=("--with-doc=skip") + CONFIG_OPTS+=("--disable-spellcheck") ;; esac # NOTE: The case "$BUILD_TYPE" above was about setting CONFIG_OPTS. From 2e590d010519209e045f90b1d78417ab71740e55 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 20 Sep 2023 13:22:02 +0200 Subject: [PATCH 1090/1232] ci_build.sh: define MAKE=... fallback default in one place Signed-off-by: Jim Klimov --- ci_build.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 503345a891..0259cf77a6 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -164,7 +164,19 @@ case "${CI_BUILDDIR-}" in ;; esac -[ -n "$MAKE" ] || [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] || MAKE=make +#[ -n "$MAKE" ] || [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] || MAKE=make +# It seems sometimes we get blanks from CI +if [ -z "`echo "${MAKE-}" | tr -d ' '`" ] ; then + if (command -v gmake) >/dev/null 2>/dev/null ; then + # GNU make processes quiet mode better, which helps with spellcheck use-case + MAKE=gmake + else + # Use system default, there should be one + MAKE=make + fi + export MAKE +fi + [ -n "$GGREP" ] || GGREP=grep [ -n "$MAKE_FLAGS_QUIET" ] || MAKE_FLAGS_QUIET="VERBOSE=0 V=0 -s" @@ -446,18 +458,6 @@ if [ -z "${PKG_CONFIG-}" ]; then PKG_CONFIG="pkg-config" fi -# It seems sometimes we get blanks from CI -if [ -z "`echo "${MAKE-}" | tr -d ' '`" ] ; then - if (command -v gmake) >/dev/null 2>/dev/null ; then - # GNU make processes quiet mode better, which helps with this use-case - MAKE=gmake - else - # Use system default, there should be one - MAKE=make - fi - export MAKE -fi - # Would hold full path to the CONFIGURE_SCRIPT="${SCRIPTDIR}/${CONFIGURE_SCRIPT_FILENAME}" CONFIGURE_SCRIPT="" autogen_get_CONFIGURE_SCRIPT() { From 13a01555106e2f3df9d353b7301244c73fa4e436 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 21 Sep 2023 10:08:05 +0200 Subject: [PATCH 1091/1232] ci_build.sh: only impose GNU make as default if spellchecking via script Signed-off-by: Jim Klimov --- ci_build.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ci_build.sh b/ci_build.sh index 0259cf77a6..66699ab2dc 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -164,14 +164,15 @@ case "${CI_BUILDDIR-}" in ;; esac -#[ -n "$MAKE" ] || [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] || MAKE=make -# It seems sometimes we get blanks from CI +# Just in case we get blanks from CI - consider them as not-set: if [ -z "`echo "${MAKE-}" | tr -d ' '`" ] ; then - if (command -v gmake) >/dev/null 2>/dev/null ; then + if [ "$1" = spellcheck -o "$1" = spellcheck-interactive ] \ + && (command -v gmake) >/dev/null 2>/dev/null \ + ; then # GNU make processes quiet mode better, which helps with spellcheck use-case MAKE=gmake else - # Use system default, there should be one + # Use system default, there should be one (or fail eventually if not) MAKE=make fi export MAKE From 7beccb53d109dd8561cf5ef4480bc3dab84ce350 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 21 Sep 2023 11:30:14 +0200 Subject: [PATCH 1092/1232] docs/nut-names.txt: add a section to define and discuss Structured naming Signed-off-by: Jim Klimov --- docs/nut-names.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index af804d2ec4..0f735a836e 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -61,6 +61,31 @@ parse the value for that variable as it may vary greatly from one UPS (or similar device) to the next. These strings are best handled directly by the user. +Structured naming +----------------- + +All standard NUT names of variables and commands are structured, with +a certain domain-specific prefix and purpose-specific suffix parts. +NUT tools provide and interpret them as dot-separated strings (although +third-party tools might restructure them by cutting and pasting at the +dot separation location, e.g. to represent as a JSON data tree or as +data model classes for specific programming languages). + +If you would be making a parser of this information, please do also note +that in some *but not all* cases there is a defined data point for some +reading or command at the "root level" of what evolved to be a collection +of further structured related information (and there are no guarantees +for future evolution in this regard), for example: + +* an `input.voltage` reports the momentary voltage level value and + there is a `input.voltage.maximum` for a certain related detail; +* conversely, there are several items like `input.transfer.reason` + but there is no actual `input.transfer` report. + +There may be more layers than two (e.g. `input.voltage.low.warning`), +and in certain cases detailed below there may be a variable component +in the practical values (e.g. the `n` in `ambient.n.temperature.alarm` +variable or `outlet.n.load.off` command names). Time and Date format -------------------- From 3094174ffa7ff93ea20651cf19aa446419be0b28 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 21 Sep 2023 11:31:12 +0200 Subject: [PATCH 1093/1232] docs/nut-names.txt: clarify that the tables of short SPEC names is just a component in longer phase-aware naming scheme Signed-off-by: Jim Klimov --- docs/nut-names.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/nut-names.txt b/docs/nut-names.txt index 0f735a836e..2c48c1959b 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -383,6 +383,10 @@ Valid CONTEXTs Valid SPECs ^^^^^^^^^^^ +NOTE: For cursory readers -- the following couple of tables lists just the +short `SPEC` component of the larger `DOMAIN.CONTEXT.SPEC` naming scheme +for phase-aware values, as discussed in other sections of this chapter. + Valid with/without context (i.e. per phase or aggregated/averaged) [options="header"] From ae492a8da15b1153feaae2c1cd8dfe3aa3fa293c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 11:40:58 +0200 Subject: [PATCH 1094/1232] data/driver.list.in: leave a note about Riello Netman "not-plus" SNMP card naming [#1878] Signed-off-by: Jim Klimov --- data/driver.list.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/driver.list.in b/data/driver.list.in index d35a1ff1b9..ac613778c6 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1096,8 +1096,8 @@ "Riello" "ups" "3" "(various)" "Netman Plus 101 SNMP Box" "snmp-ups" "Riello" "ups" "3" "(various)" "Netman Plus 102 SNMP Card" "snmp-ups" "Riello" "ups" "3" "(various)" "Netman Plus 202 SNMP Card" "snmp-ups" -"Riello" "ups" "3" "(various)" "Netman 204 SNMP Card" "snmp-ups" -"Riello" "ups" "3" "(various)" "Netman 208 SNMP Card" "snmp-ups" +"Riello" "ups" "3" "(various)" "Netman 204 SNMP Card" "snmp-ups" # Note: in https://github.com/networkupstools/nut/issues/1878 submitted not as "Netman Plus", clarification requested +"Riello" "ups" "3" "(various)" "Netman 208 SNMP Card" "snmp-ups" # Note: in https://github.com/networkupstools/nut/issues/1878 submitted not as "Netman Plus", clarification requested "Rocketfish" "ups" "3" "RF-1000VA / RF-1025VA" "USB" "usbhid-ups" From 289dd3c492387778ab1b6b93d9b0d59394842104 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 12:13:09 +0200 Subject: [PATCH 1095/1232] common.{c,h}: introduce upsdebugx_report_search_paths() [#317] Signed-off-by: Jim Klimov --- common/common.c | 14 ++++++++++++++ include/common.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/common/common.c b/common/common.c index 16228665a5..6dda17d051 100644 --- a/common/common.c +++ b/common/common.c @@ -1912,6 +1912,20 @@ static const char * search_paths[] = { NULL }; +void upsdebugx_report_search_paths(int level) { + size_t index; + + if (nut_debug_level < level) + return; + + + upsdebugx(level, "Run-time loadable library search paths used by this build of NUT:"); + for (index = 0; search_paths[index] != NULL; index++) + { + upsdebugx(level, "\t%s", search_paths[index]); + } +} + static char * get_libname_in_dir(const char* base_libname, size_t base_libname_length, const char* dirname, int index) { /* Implementation detail for get_libname() below. * Returns pointer to allocated copy of the buffer diff --git a/include/common.h b/include/common.h index 31a10a8fc4..1b5a4bd320 100644 --- a/include/common.h +++ b/include/common.h @@ -334,6 +334,10 @@ void fatalx(int status, const char *fmt, ...) */ void nut_report_config_flags(void); +/* Report search paths used by ltdl-augmented code to discover and + * load shared binary object files at run-time (nut-scanner, DMF...) */ +void upsdebugx_report_search_paths(int level); + extern int nut_debug_level; extern int nut_log_level; From 51c8dc71b6c79ea53e7fcc2b8137879c80195605 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 12:16:05 +0200 Subject: [PATCH 1096/1232] nut-scanner: use upsdebugx_report_search_paths() [#317] Also bumps public API version of libnutscan due to added symbol. Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++++ UPGRADING.adoc | 4 ++++ tools/nut-scanner/Makefile.am | 5 +++-- tools/nut-scanner/nut-scanner.c | 4 ++++ tools/nut-scanner/nutscan-init.c | 3 +++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index c132b8cce5..1168dfaf89 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -275,6 +275,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. this variable unless troubleshooting, although other systems rely on it) [#805] + - The `nut-scanner` usage and debug printouts now include the loadable library + search paths, to help troubleshooting especially in multi-platform builds + [#317] + - The nut-scanner program was updated to fall back to loading unresolved library filenames, hoping that `lt_dlopen()` implementation on the current platform would find library files better [#805] diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 3c40e19f8e..9e0e989a01 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -124,6 +124,10 @@ Changes from 2.8.0 to 2.8.1 or explicitly forfeit building the tool (some distro packages missed it quietly in the past) [#1560] +- An `upsdebugx_report_search_paths()` method in NUT common code was added, + and exposed in `libnutscan.so` builds in particular - API version for the + public library was bumped [#317] + - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index a79dd0bc6f..c7d91db616 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -16,6 +16,7 @@ $(NUT_SCANNER_DEPS): dummy @cd .. && $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps # Make sure out-of-dir dependencies exist (especially when dev-building parts): +$(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libcommon.la: dummy @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) @@ -79,7 +80,7 @@ endif # object .so names would differ) # # libnutscan version information -libnutscan_la_LDFLAGS += -version-info 2:1:0 +libnutscan_la_LDFLAGS += -version-info 2:2:0 # libnutscan exported symbols regex # WARNING: Since the library includes parts of libcommon (as much as needed @@ -90,7 +91,7 @@ libnutscan_la_LDFLAGS += -version-info 2:1:0 # copies of "nut_debug_level" making fun of our debug-logging attempts. # One solution to tackle if needed for those cases would be to make some # dynamic/shared libnutcommon (etc.) -libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads|nut_report_config_flags)' +libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads|nut_report_config_flags|upsdebugx_report_search_paths)' libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include \ $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index aed5624792..bd95b2c563 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -217,6 +217,10 @@ static void show_usage(void) printf(" -T, --thread : Limit the amount of scanning threads running simultaneously (not implemented in this build: no pthread support)"); #endif + printf("\nNote: many scanning options depend on further loadable libraries.\n"); + /* Note: if debug is enabled, this is prefixed with timestamps */ + upsdebugx_report_search_paths(0); + printf("\nNetwork specific options:\n"); printf(" -t, --timeout : network operation timeout (default %d).\n", DEFAULT_NETWORK_TIMEOUT); printf(" -s, --start_ip : First IP address to scan.\n"); diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index f3829b95c1..81d8d5a6d9 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -110,6 +110,9 @@ void nutscan_init(void) { char *libname = NULL; + /* Report library paths we would search, at given debug verbosity level */ + upsdebugx_report_search_paths(1); + #ifdef HAVE_PTHREAD /* TOTHINK: Should semaphores to limit thread count * and the more naive but portable methods be an From 1d1aab5943e4435b8e434df63f6e10e099ffd054 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 13:10:24 +0200 Subject: [PATCH 1097/1232] common/common.c: comment about peculiarities of search_paths[] contents [#317] Signed-off-by: Jim Klimov --- common/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index 6dda17d051..e28b8f6566 100644 --- a/common/common.c +++ b/common/common.c @@ -1855,8 +1855,8 @@ ssize_t select_write(serial_handler_t *fd, const void *buf, const size_t buflen, static const char * search_paths[] = { /* Use the library path (and bitness) provided during ./configure first */ LIBDIR, - "/usr"LIBDIR, - "/usr/local"LIBDIR, + "/usr"LIBDIR, /* Note: this can lead to bogus strings like */ + "/usr/local"LIBDIR, /* "/usr/usr/lib" which would be ignored quickly */ #ifdef BUILD_64 /* Fall back to explicit preference of 64-bit paths as named on some OSes */ "/usr/lib/64", From 05024713acbf0ffdd3d111f47259b1116ff502b5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 13:11:21 +0200 Subject: [PATCH 1098/1232] common/common.c: extend upsdebugx_report_search_paths() to follow actual search order of get_libname() with more locations possibly checked [#317] Signed-off-by: Jim Klimov --- common/common.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index e28b8f6566..026f2c0056 100644 --- a/common/common.c +++ b/common/common.c @@ -1914,16 +1914,57 @@ static const char * search_paths[] = { void upsdebugx_report_search_paths(int level) { size_t index; + char *s, *varname; if (nut_debug_level < level) return; - upsdebugx(level, "Run-time loadable library search paths used by this build of NUT:"); + + /* NOTE: Reporting order follows get_libname(), and + * while some values are individual paths, others can + * be "pathsets" (e.g. coming envvars) with certain + * platform-dependent separator characters. */ +#ifdef BUILD_64 + varname = "LD_LIBRARY_PATH_64"; +#else + varname = "LD_LIBRARY_PATH_32"; +#endif + + if (((s = getenv(varname)) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tVia %s:\t%s", varname, s); + } + + varname = "LD_LIBRARY_PATH"; + if (((s = getenv(varname)) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tVia %s:\t%s", varname, s); + } + for (index = 0; search_paths[index] != NULL; index++) { - upsdebugx(level, "\t%s", search_paths[index]); + upsdebugx(level, "\tBuilt-in:\t%s", search_paths[index]); + } + +#ifdef WIN32 + if (((s = getfullpath(NULL)) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tWindows near EXE:\t%s", s); + } + +# ifdef PATH_LIB + if (((s = getfullpath(PATH_LIB)) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tWindows PATH_LIB (%s):\t%s", PATH_LIB, s); } +# endif + + if (((s = getfullpath("/../lib")) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tWindows \"lib\" dir near EXE:\t%s", s); + } + + varname = "PATH"; + if (((s = getenv(varname)) != NULL) && strlen(s) > 0) { + upsdebugx(level, "\tWindows via %s:\t%s", varname, s); + } +#endif } static char * get_libname_in_dir(const char* base_libname, size_t base_libname_length, const char* dirname, int index) { @@ -2056,6 +2097,8 @@ static char * get_libname_in_pathset(const char* base_libname, size_t base_libna char * get_libname(const char* base_libname) { + /* NOTE: Keep changes to practical search order + * synced to upsdebugx_report_search_paths() */ int index = 0, counter = 0; char *libname_path = NULL; size_t base_libname_length = strlen(base_libname); From 4e893fe49627bcb68c26573d870e8f6e7ddfc308 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 13:56:28 +0200 Subject: [PATCH 1099/1232] common/common.c: vupslog(): print timestamp+buf in one operation Signed-off-by: Jim Klimov --- common/common.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/common/common.c b/common/common.c index 026f2c0056..99db2ee684 100644 --- a/common/common.c +++ b/common/common.c @@ -1287,11 +1287,15 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) now.tv_sec -= 1; } - fprintf(stderr, "%4.0f.%06ld\t", + /* 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)); + (long)(now.tv_usec - upslog_start.tv_usec), + buf); + } else { + fprintf(stderr, "%s\n", buf); } - fprintf(stderr, "%s\n", buf); #ifdef WIN32 fflush(stderr); #endif From 501aaa5512f76b865ac83d9448b0be71395ebe44 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 13:57:44 +0200 Subject: [PATCH 1100/1232] configure.ac, common/common.c: search_paths[]: introduce MULTIARCH_TARGET_ALIAS as/if suggested by compiler [#317] Signed-off-by: Jim Klimov --- common/common.c | 13 +++++++++++++ configure.ac | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/common/common.c b/common/common.c index 99db2ee684..764982ebd8 100644 --- a/common/common.c +++ b/common/common.c @@ -1861,6 +1861,19 @@ static const char * search_paths[] = { LIBDIR, "/usr"LIBDIR, /* Note: this can lead to bogus strings like */ "/usr/local"LIBDIR, /* "/usr/usr/lib" which would be ignored quickly */ +/* TOTHINK: Should AUTOTOOLS_* specs also be highly preferred? + * Currently they are listed after the "legacy" hard-coded paths... + */ +#ifdef MULTIARCH_TARGET_ALIAS +# ifdef BUILD_64 + "/usr/lib/64/" MULTIARCH_TARGET_ALIAS, + "/usr/lib64/" MULTIARCH_TARGET_ALIAS, + "/lib/64/" MULTIARCH_TARGET_ALIAS, + "/lib64/" MULTIARCH_TARGET_ALIAS, +# endif /* MULTIARCH_TARGET_ALIAS && BUILD_64 */ + "/usr/lib/" MULTIARCH_TARGET_ALIAS, + "/lib/" MULTIARCH_TARGET_ALIAS, +#endif /* MULTIARCH_TARGET_ALIAS */ #ifdef BUILD_64 /* Fall back to explicit preference of 64-bit paths as named on some OSes */ "/usr/lib/64", diff --git a/configure.ac b/configure.ac index 0df68d1e8c..10c9f16400 100644 --- a/configure.ac +++ b/configure.ac @@ -3860,6 +3860,14 @@ if test -n "${target_cpu}" -a -n "${target_os}" ; then NUT_REPORT_TARGET(AUTOTOOLS_TARGET_SHORT_ALIAS, "${target_cpu}-${target_os}", [host OS short spec we built for]) fi +AC_MSG_CHECKING([whether compiler suggests a MULTIARCH value]) +dnl Recent GCC generally supports this call, although it often returns empty +dnl Some versions of CLANG also have it, others reject the unknown CLI switch +compiler_multiarch="`${CC} -print-multiarch 2>/dev/null`" || compiler_multiarch="" +if test -n "${compiler_multiarch}" ; then + NUT_REPORT_TARGET(MULTIARCH_TARGET_ALIAS, "${compiler_multiarch}", [host multiarch spec we build for (as suggested by compiler being used)]) +fi + dnl ---------------------------------------------------------------------- dnl Check the user and group to run as last, so we can use the paths configured dnl above as data sources for default values if building an in-place replacement From c7f8fe5118b55f5dec297c475ca3bda5c11e360e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 14:14:25 +0200 Subject: [PATCH 1101/1232] common/common.c: fix get_libname_in_pathset() mutilating the input pathset string It was unexpected to see just one entry in getenv("PATH") after the first loop... Signed-off-by: Jim Klimov --- common/common.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/common/common.c b/common/common.c index 764982ebd8..2626591c16 100644 --- a/common/common.c +++ b/common/common.c @@ -2083,30 +2083,37 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l static char * get_libname_in_pathset(const char* base_libname, size_t base_libname_length, char* pathset, int *counter) { /* Note: this method iterates specified pathset, - * so increments the counter by reference */ + * so it increments the counter by reference. + * A copy of original pathset is used, because + * strtok() tends to modify its input! */ char *libname_path = NULL; char *onedir = NULL; + char* pathset_tmp; if (!pathset || *pathset == '\0') return NULL; /* First call to tokenization passes the string, others pass NULL */ - while (NULL != (onedir = strtok( (onedir ? NULL : pathset), ":" ))) { + pathset_tmp = xstrdup(pathset); + 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) break; } + free(pathset_tmp); #ifdef WIN32 /* Note: with mingw, the ":" separator above might have been resolvable */ + pathset_tmp = xstrdup(pathset); if (!libname_path) { onedir = NULL; /* probably is NULL already, but better ensure this */ - while (NULL != (onedir = strtok( (onedir ? NULL : pathset), ";" ))) { + 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) break; } } + free(pathset_tmp); #endif /* WIN32 */ return libname_path; From 3c482e95fbb2dc9a4a29a38099bce8bd3cc74793 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 15:03:28 +0200 Subject: [PATCH 1102/1232] common/common.c: fix get_libname_in_pathset() increment of checked-directory counter Be sure to bump the number, not the pointer! Signed-off-by: Jim Klimov --- common/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index 2626591c16..2983879f18 100644 --- a/common/common.c +++ b/common/common.c @@ -2096,7 +2096,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); while (NULL != (onedir = strtok( (onedir ? NULL : pathset_tmp), ":" ))) { - libname_path = get_libname_in_dir(base_libname, base_libname_length, onedir, *counter++); + libname_path = get_libname_in_dir(base_libname, base_libname_length, onedir, (*counter)++); if (libname_path != NULL) break; } @@ -2108,7 +2108,7 @@ static char * get_libname_in_pathset(const char* base_libname, size_t base_libna if (!libname_path) { onedir = NULL; /* probably is NULL already, but better ensure this */ while (NULL != (onedir = strtok( (onedir ? NULL : pathset_tmp), ";" ))) { - libname_path = get_libname_in_dir(base_libname, base_libname_length, onedir, *counter++); + libname_path = get_libname_in_dir(base_libname, base_libname_length, onedir, (*counter)++); if (libname_path != NULL) break; } From 417311041598d6a2fcb5e40b966a204072eeecfb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 15:19:02 +0200 Subject: [PATCH 1103/1232] common/common.c: vupslog(): stash errno value at start of method, so later calls do not corrupt what we want to report; fix declarations-on-top for windows builds Signed-off-by: Jim Klimov --- common/common.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/common/common.c b/common/common.c index 2983879f18..bbeb3208fe 100644 --- a/common/common.c +++ b/common/common.c @@ -1217,7 +1217,7 @@ void nut_report_config_flags(void) static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { - int ret; + int ret, errno_orig = errno; char buf[LARGEBUF]; #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL @@ -1234,6 +1234,8 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) #pragma clang diagnostic ignored "-Wformat-nonliteral" #pragma clang diagnostic ignored "-Wformat-security" #endif + /* Note: errors here can reset errno, + * so errno_orig is stashed beforehand */ ret = vsnprintf(buf, sizeof(buf), fmt, va); #ifdef __clang__ #pragma clang diagnostic pop @@ -1247,11 +1249,14 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) LARGEBUF); if (use_strerror) { - snprintfcat(buf, sizeof(buf), ": %s", strerror(errno)); - #ifdef WIN32 LPVOID WinBuf; DWORD WinErr = GetLastError(); +#endif + + snprintfcat(buf, sizeof(buf), ": %s", strerror(errno_orig)); + +#ifdef WIN32 FormatMessage( FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ALLOCATE_BUFFER | From 3ecfa78fb79685986a70bcf0f630b7b1bfc5b68a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 16:32:46 +0200 Subject: [PATCH 1104/1232] common/common.c: vupslogx(): dynamically adjust the needed buffer size for longer printouts, e.g. PATH in upsdebugx_report_search_paths() [#317] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 ++++ common/common.c | 79 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 1168dfaf89..5220ab3510 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -275,6 +275,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. this variable unless troubleshooting, although other systems rely on it) [#805] + - Debug information tracing methods like `upsdebugx()` should now be less + limited in the sizes of messages that they can print, such as path names + that may be quite long. Note that the OS methods manipulating the strings, + and receivers such as logging systems, may still impose limits of their own. + - The `nut-scanner` usage and debug printouts now include the loadable library search paths, to help troubleshooting especially in multi-platform builds [#317] diff --git a/common/common.c b/common/common.c index bbeb3208fe..b567321628 100644 --- a/common/common.c +++ b/common/common.c @@ -1218,7 +1218,11 @@ void nut_report_config_flags(void) static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret, errno_orig = errno; - char buf[LARGEBUF]; + size_t bufsize = LARGEBUF; + char *buf = xcalloc(sizeof(char), bufsize); + + /* Be pedantic about our limitations */ + bufsize *= sizeof(char); #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL #pragma GCC diagnostic push @@ -1236,7 +1240,69 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) #endif /* Note: errors here can reset errno, * so errno_orig is stashed beforehand */ - ret = vsnprintf(buf, sizeof(buf), fmt, va); + do { + ret = vsnprintf(buf, bufsize, fmt, va); + + if ((ret < 0) || ((uintmax_t)ret >= (uintmax_t)bufsize)) { + /* Try to adjust bufsize until we can print the + * whole message. Note that standards only require + * up to 4095 bytes to be manageable in printf-like + * methods: + * The number of characters that can be produced + * by any single conversion shall be at least 4095. + * C17dr § 7.21.6.1 15 + * In general, vsnprintf() is not specified to set + * errno on any condition (or to not implement a + * larger limit). Select implementations may do so + * though. + * Based on https://stackoverflow.com/a/72981237/4715872 + */ + if (bufsize < SIZE_MAX/2) { + size_t newbufsize = bufsize*2; + if (ret > 0) { + /* Be generous, we snprintfcat() some + * suffixes, prefix a timestamp, etc. */ + if (((uintmax_t)ret) > (SIZE_MAX - LARGEBUF)) { + goto vupslog_too_long; + } + newbufsize = ret + LARGEBUF; + } /* else: errno, e.g. ERANGE printing: + * "...(34 => Result too large)" */ + if (nut_debug_level > 0) { + fprintf(stderr, "WARNING: vupslog: " + "vsnprintf needed more than %" + PRIuSIZE " bytes: %d (%d => %s)," + " extending to %" PRIuSIZE "\n", + bufsize, ret, + errno, strerror(errno), + newbufsize); + } + bufsize = newbufsize; + buf = xrealloc(buf, bufsize); + continue; + } + } else { + /* All fits well now; majority of use-cases should + * have nailed this on first try (envvar prints of + * longer fully-qualified PATHs, compilation settings + * reports etc. may need more). Even a LARGEBUF may + * still overflow some older syslog buffers and would + * be truncated there. At least stderr would see as + * complete a picture as we can give it. + */ + break; + } + + /* Arbitrary limit, gotta stop somewhere */ + if (bufsize > LARGEBUF * 64) { +vupslog_too_long: + syslog(LOG_WARNING, "vupslog: vsnprintf needed " + "more than %" PRIuSIZE " bytes; logged " + "output can be truncated", + bufsize); + break; + } + } while(1); #ifdef __clang__ #pragma clang diagnostic pop #endif @@ -1244,17 +1310,13 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) #pragma GCC diagnostic pop #endif - if ((ret < 0) || (ret >= (int) sizeof(buf))) - syslog(LOG_WARNING, "vupslog: vsnprintf needed more than %d bytes", - LARGEBUF); - if (use_strerror) { #ifdef WIN32 LPVOID WinBuf; DWORD WinErr = GetLastError(); #endif - snprintfcat(buf, sizeof(buf), ": %s", strerror(errno_orig)); + snprintfcat(buf, bufsize, ": %s", strerror(errno_orig)); #ifdef WIN32 FormatMessage( @@ -1268,7 +1330,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) (LPTSTR) &WinBuf, 0, NULL ); - snprintfcat(buf, sizeof(buf), " [%s]", (char *)WinBuf); + snprintfcat(buf, bufsize, " [%s]", (char *)WinBuf); LocalFree(WinBuf); #endif } @@ -1307,6 +1369,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) } if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) syslog(priority, "%s", buf); + free(buf); } From 8c04c7f9e3ce8f31d5e9dd5c22c5e37d3c58efd2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 16:51:08 +0200 Subject: [PATCH 1105/1232] tools/nut-scanner/nut-scanner.c: typo (lacking newline) in an usage message Signed-off-by: Jim Klimov --- tools/nut-scanner/nut-scanner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index bd95b2c563..0028e12962 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -214,7 +214,7 @@ static void show_usage(void) #if (defined HAVE_PTHREAD) && (defined HAVE_PTHREAD_TRYJOIN) printf(" -T, --thread : Limit the amount of scanning threads running simultaneously (default: %" PRIuSIZE ").\n", max_threads); #else - printf(" -T, --thread : Limit the amount of scanning threads running simultaneously (not implemented in this build: no pthread support)"); + printf(" -T, --thread : Limit the amount of scanning threads running simultaneously (not implemented in this build: no pthread support)\n"); #endif printf("\nNote: many scanning options depend on further loadable libraries.\n"); From 47400234dab212f068f42accfadd36e63e97cb7b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 18:12:24 +0200 Subject: [PATCH 1106/1232] tests/NIT/nit.sh: consider an empty output of nut-scanner an error (to retry from one mode to another) Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 7debf2e178..4b132224ba 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1150,6 +1150,7 @@ testcase_sandbox_nutscanner_list() { # NOTE: Currently mask mode is IPv4 only runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -m 127.0.0.1/32 -O -p "${NUT_PORT}" \ + && test -n "$CMDOUT" \ || runcmd "${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner" -s localhost -O -p "${NUT_PORT}" LD_LIBRARY_PATH="${LD_LIBRARY_PATH_ORIG}" From 472ab1ed68233a65eeaedc066fbbdd92a3e85a76 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 18:14:57 +0200 Subject: [PATCH 1107/1232] tools/nut-scanner/nutscan-ip.c: trace getaddrinfo() failures Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-ip.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 4fc410d2fc..6c319d898e 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -269,6 +269,7 @@ int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) nutscan_ip_iter_t ip; int mask_val; int mask_byte; + int ret; uint32_t mask_bit; /* 32-bit IPv4 address bitmask */ char host[SMALLBUF]; struct addrinfo hints; @@ -319,14 +320,17 @@ int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) hints.ai_family = AF_INET; ip.type = IPv4; - /* Detecting IPv4 vs IPv6 */ - if (getaddrinfo(first_ip, NULL, &hints, &res) != 0) { - /*Try IPv6 detection */ - int ret; + if ((ret = getaddrinfo(first_ip, NULL, &hints, &res)) != 0) { + /* EAI_ADDRFAMILY? */ + upsdebugx(5, "%s: getaddrinfo() failed for AF_INET (IPv4): %d", + __func__, ret); + /* Try IPv6 detection */ ip.type = IPv6; hints.ai_family = AF_INET6; if ((ret = getaddrinfo(first_ip, NULL, &hints, &res)) != 0) { + upsdebugx(5, "%s: getaddrinfo() failed for AF_INET6 (IPv6): %d", + __func__, ret); free(first_ip); return 0; } From 4ed9dc91dcd5c6617ff9c51b02925921b32107e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 18:16:00 +0200 Subject: [PATCH 1108/1232] tools/nut-scanner/nutscan-ip.c: WIN32 builds require WSAStartup() before getaddrinfo() et al Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-ip.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 6c319d898e..4223bfa868 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -279,6 +279,9 @@ int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) *start_ip = NULL; *stop_ip = NULL; +#ifdef WIN32 + WSADATA WSAdata; +#endif cidr_tok = strdup(cidr); first_ip = strdup(strtok_r(cidr_tok, "/", &saveptr)); @@ -320,6 +323,12 @@ int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) hints.ai_family = AF_INET; ip.type = IPv4; + +#ifdef WIN32 + WSAStartup(2,&WSAdata); + atexit((void(*)(void))WSACleanup); +#endif + if ((ret = getaddrinfo(first_ip, NULL, &hints, &res)) != 0) { /* EAI_ADDRFAMILY? */ upsdebugx(5, "%s: getaddrinfo() failed for AF_INET (IPv4): %d", From 54cc41612a2f408c4102aa36463c2d35030b996a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 18:23:45 +0200 Subject: [PATCH 1109/1232] common, nut-scanner: Introduce nut_prepare_search_paths() to pre-filter the usable set [#317] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +- common/common.c | 110 +++++++++++++++++++++++++++++-- include/common.h | 3 +- tools/nut-scanner/Makefile.am | 2 +- tools/nut-scanner/nut-scanner.c | 2 +- tools/nut-scanner/nutscan-init.c | 5 +- 6 files changed, 117 insertions(+), 10 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 5220ab3510..de559cf130 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -281,8 +281,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. and receivers such as logging systems, may still impose limits of their own. - The `nut-scanner` usage and debug printouts now include the loadable library - search paths, to help troubleshooting especially in multi-platform builds - [#317] + search paths, to help troubleshooting especially in multi-platform builds; + pre-filtering of the built-in paths was introduced (to walk only existing + and unique directory names) [#317] - The nut-scanner program was updated to fall back to loading unresolved library filenames, hoping that `lt_dlopen()` implementation on the current diff --git a/common/common.c b/common/common.c index b567321628..cd13aad4ef 100644 --- a/common/common.c +++ b/common/common.c @@ -1924,7 +1924,7 @@ ssize_t select_write(serial_handler_t *fd, const void *buf, const size_t buflen, * linked against certain OS-provided libraries for accessing this or that * communications media and/or vendor protocol. */ -static const char * search_paths[] = { +static const char * search_paths_builtin[] = { /* Use the library path (and bitness) provided during ./configure first */ LIBDIR, "/usr"LIBDIR, /* Note: this can lead to bogus strings like */ @@ -1997,9 +1997,106 @@ static const char * search_paths[] = { NULL }; -void upsdebugx_report_search_paths(int level) { +static const char ** search_paths = search_paths_builtin; + +/* free this when a NUT program ends (common library is unloaded) + * IFF it is not the built-in version. */ +static void nut_free_search_paths(void) { + if (search_paths == NULL) { + search_paths = search_paths_builtin; + return; + } + + if (search_paths != search_paths_builtin) { + /* TODO: if nut_prepare_search_paths() is later + * extended to track not only built-in strings, + * change that to use an array of xstrdup()'ed + * strings, and free() those dupes here. + */ + free(search_paths); + search_paths = search_paths_builtin; + } +} + +void nut_prepare_search_paths(void) { + /* Produce the search_paths[] with minimal confusion allowing + * for faster walks and fewer logs in NUT applications: + * * only existing paths + * * discard lower-priority duplicates if a path is already listed + * + * NOTE: Currently this only trims info from search_paths_builtin[] + * but might later supplant iterations in the get_libname(), + * get_libname_in_pathset() and upsdebugx_report_search_paths() + * methods. Surely would make their code easier, but at a cost of + * probably losing detailed logging of where something came from... + */ + static int atexit_hooked = 0; + size_t count_builtin = 0, count_filtered = 0, i, j, index = 0; + const char ** filtered_search_paths; + DIR *dp; + + /* 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++) {} + count_builtin = i + 1; /* +1 for the NULL */ + + /* Bytes inside should all be zeroed... */ + filtered_search_paths = xcalloc(sizeof(const char *), count_builtin); + + /* FIXME: here "count_builtin" means size of filtered_search_paths[] + * and may later be more, if we would consider other data sources */ + for (i = 0; search_paths_builtin[i] != NULL && count_filtered < count_builtin; i++) { + /* NOTE: not xstrdup()ing here now, remember to check + * nut_free_search_paths() if it later would be */ + int dupe = 0; + if ((dp = opendir(search_paths_builtin[i])) == NULL) { + upsdebugx(5, "%s: SKIP " + "unreachable directory #%" PRIuSIZE " : %s", + __func__, index++, search_paths_builtin[i]); + continue; + } + index++; + + /* Revise for duplicates */ + /* Note: (count_filtered == 0) means first existing dir seen, no hassle */ + for (j = 0; j < count_filtered; j++) { + if (!strcmp(filtered_search_paths[j], search_paths_builtin[i])) { + upsdebugx(5, "%s: SKIP " + "duplicate directory #%" PRIuSIZE " : %s", + __func__, index, search_paths_builtin[i]); + dupe = 1; + break; + } + } + + if (!dupe) { + upsdebugx(5, "%s: ADD " + "existing unique directory #%" PRIuSIZE " : %s", + __func__, count_filtered, search_paths_builtin[i]); + filtered_search_paths[count_filtered] = search_paths_builtin[i]; + count_filtered++; + } + } + + /* If we mangled this before, forget the old result: */ + nut_free_search_paths(); + + filtered_search_paths[count_filtered] = NULL; + search_paths = filtered_search_paths; + + if (!atexit_hooked) { + atexit(nut_free_search_paths); + atexit_hooked = 1; + } +} + +void upsdebugx_report_search_paths(int level, int report_search_paths_builtin) { size_t index; char *s, *varname; + const char ** reported_search_paths = ( + report_search_paths_builtin + ? search_paths_builtin + : search_paths); if (nut_debug_level < level) return; @@ -2025,9 +2122,14 @@ void upsdebugx_report_search_paths(int level) { upsdebugx(level, "\tVia %s:\t%s", varname, s); } - for (index = 0; search_paths[index] != NULL; index++) + for (index = 0; reported_search_paths[index] != NULL; index++) { - upsdebugx(level, "\tBuilt-in:\t%s", search_paths[index]); + if (index == 0) { + upsdebugx(level, "\tNOTE: Reporting %s built-in paths:", + (report_search_paths_builtin ? "raw" + : "filtered (existing unique)")); + } + upsdebugx(level, "\tBuilt-in:\t%s", reported_search_paths[index]); } #ifdef WIN32 diff --git a/include/common.h b/include/common.h index 1b5a4bd320..7f4a1a5638 100644 --- a/include/common.h +++ b/include/common.h @@ -336,7 +336,8 @@ void nut_report_config_flags(void); /* Report search paths used by ltdl-augmented code to discover and * load shared binary object files at run-time (nut-scanner, DMF...) */ -void upsdebugx_report_search_paths(int level); +void upsdebugx_report_search_paths(int level, int report_search_paths_builtin); +void nut_prepare_search_paths(void); extern int nut_debug_level; extern int nut_log_level; diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index c7d91db616..0a5108d798 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -91,7 +91,7 @@ libnutscan_la_LDFLAGS += -version-info 2:2:0 # copies of "nut_debug_level" making fun of our debug-logging attempts. # One solution to tackle if needed for those cases would be to make some # dynamic/shared libnutcommon (etc.) -libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads|nut_report_config_flags|upsdebugx_report_search_paths)' +libnutscan_la_LDFLAGS += -export-symbols-regex '^(nutscan_|nut_debug_level|s_upsdebugx|max_threads|curr_threads|nut_report_config_flags|upsdebugx_report_search_paths|nut_prepare_search_paths)' libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include \ $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 0028e12962..9e84d77ec2 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -219,7 +219,7 @@ static void show_usage(void) printf("\nNote: many scanning options depend on further loadable libraries.\n"); /* Note: if debug is enabled, this is prefixed with timestamps */ - upsdebugx_report_search_paths(0); + upsdebugx_report_search_paths(0, 0); printf("\nNetwork specific options:\n"); printf(" -t, --timeout : network operation timeout (default %d).\n", DEFAULT_NETWORK_TIMEOUT); diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 81d8d5a6d9..c2ae3c3751 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -110,8 +110,11 @@ void nutscan_init(void) { char *libname = NULL; + /* Optional filter to not walk things twice */ + nut_prepare_search_paths(); + /* Report library paths we would search, at given debug verbosity level */ - upsdebugx_report_search_paths(1); + upsdebugx_report_search_paths(1, 1); #ifdef HAVE_PTHREAD /* TOTHINK: Should semaphores to limit thread count From 73e6f237ea74006ed494e9d81849e7a1dbeadd95 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Sep 2023 19:49:06 +0200 Subject: [PATCH 1110/1232] common/common.c: nut_prepare_search_paths(): use realpath() where available, and so xstrdup()/free() in general [#317] Signed-off-by: Jim Klimov --- common/common.c | 52 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/common/common.c b/common/common.c index cd13aad4ef..85d42973fc 100644 --- a/common/common.c +++ b/common/common.c @@ -2008,11 +2008,10 @@ static void nut_free_search_paths(void) { } if (search_paths != search_paths_builtin) { - /* TODO: if nut_prepare_search_paths() is later - * extended to track not only built-in strings, - * change that to use an array of xstrdup()'ed - * strings, and free() those dupes here. - */ + size_t i; + for (i = 0; search_paths[i] != NULL; i++) { + free((char *)search_paths[i]); + } free(search_paths); search_paths = search_paths_builtin; } @@ -2046,41 +2045,62 @@ void nut_prepare_search_paths(void) { /* FIXME: here "count_builtin" means size of filtered_search_paths[] * and may later be more, if we would consider other data sources */ for (i = 0; search_paths_builtin[i] != NULL && count_filtered < count_builtin; i++) { - /* NOTE: not xstrdup()ing here now, remember to check - * nut_free_search_paths() if it later would be */ int dupe = 0; - if ((dp = opendir(search_paths_builtin[i])) == NULL) { + const char *dirname = search_paths_builtin[i]; + + if ((dp = opendir(dirname)) == NULL) { upsdebugx(5, "%s: SKIP " "unreachable directory #%" PRIuSIZE " : %s", - __func__, index++, search_paths_builtin[i]); + __func__, index++, dirname); continue; } index++; +#if HAVE_DECL_REALPATH + /* allocates the buffer we free() later */ + dirname = (const char *)realpath(dirname, NULL); +#endif + /* Revise for duplicates */ /* Note: (count_filtered == 0) means first existing dir seen, no hassle */ for (j = 0; j < count_filtered; j++) { - if (!strcmp(filtered_search_paths[j], search_paths_builtin[i])) { + if (!strcmp(filtered_search_paths[j], dirname)) { +#if HAVE_DECL_REALPATH + if (strcmp(search_paths_builtin[i], dirname)) { + /* They differ, highlight it */ + upsdebugx(5, "%s: SKIP " + "duplicate directory #%" PRIuSIZE " : %s (%s)", + __func__, index, dirname, + search_paths_builtin[i]); + } else +#endif upsdebugx(5, "%s: SKIP " "duplicate directory #%" PRIuSIZE " : %s", - __func__, index, search_paths_builtin[i]); + __func__, index, dirname); + dupe = 1; +#if HAVE_DECL_REALPATH + free((char *)dirname); +#endif break; } } if (!dupe) { - upsdebugx(5, "%s: ADD " - "existing unique directory #%" PRIuSIZE " : %s", - __func__, count_filtered, search_paths_builtin[i]); - filtered_search_paths[count_filtered] = search_paths_builtin[i]; - count_filtered++; + upsdebugx(5, "%s: ADD[#%" PRIuSIZE "] " + "existing unique directory: %s", + __func__, count_filtered, dirname); +#if !HAVE_DECL_REALPATH + dirname = (const char *)xstrdup(dirname); +#endif + filtered_search_paths[count_filtered++] = dirname; } } /* If we mangled this before, forget the old result: */ nut_free_search_paths(); + /* Better safe than sorry: */ filtered_search_paths[count_filtered] = NULL; search_paths = filtered_search_paths; From 7c9405cfc13d13b5412262284d7b75b33cb7b5e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 00:20:43 +0000 Subject: [PATCH 1111/1232] drivers/snmp-ups.c: fix the dangling pointer warning some compilers have found [#823] --- drivers/snmp-ups.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index ba9f5438e2..65a19397dc 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -1783,6 +1783,8 @@ void su_alarm_set(snmp_info_t *su_info_p, long value) if ((info_value = su_find_infoval(su_info_p->oid2info, &value)) != NULL && info_value[0] != 0) { + char alarm_info_value_more[SU_LARGEBUF + 32]; /* can sprintf() SU_LARGEBUF plus markup into here */ + /* Special handling for outlet & outlet groups alarms */ if ((su_info_p->flags & SU_OUTLET) || (su_info_p->flags & SU_OUTLET_GROUP)) { @@ -1803,7 +1805,6 @@ void su_alarm_set(snmp_info_t *su_info_p, long value) * start of path */ if (info_type[0] == 'L') { /* Extract phase number */ - char alarm_info_value_more[SU_LARGEBUF + 32]; /* can sprintf() SU_LARGEBUF plus markup into here */ item_number = atoi(info_type+1); From 14b808b4797ebe6acc2be8cb3737e1331d8a2b12 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 00:39:02 +0000 Subject: [PATCH 1112/1232] tests/generic_gpio_*.c: fix clang warnings [#823] --- tests/generic_gpio_liblocal.c | 11 ++++++----- tests/generic_gpio_utest.c | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c index d8ad77074a..afd7ec32f9 100644 --- a/tests/generic_gpio_liblocal.c +++ b/tests/generic_gpio_liblocal.c @@ -75,17 +75,18 @@ void setNextLinesReadToFail(void) { int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, int *values) { + int pinPos = 1; NUT_UNUSED_VARIABLE(bulk); + if(errReqFor_line_get_value_bulk) { errReqFor_line_get_value_bulk=0; errno = EPERM; return -1; } - int pinPos=1; - for(unsigned int i=0; iupsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); for(int j=0; jupsLinesCount; j++) { @@ -238,10 +244,6 @@ int main(int argc, char **argv) { if(strcmp(chargeLow, ".")) dstate_setinfo("battery.charge.low", "%s", chargeLow); jmp_result = setjmp(env_buffer); - int failed=0; - const char *currUpsStatus=NULL; - const char *currChargerStatus=NULL; - const char *currCharge=NULL; if(jmp_result) { failed=1; generic_gpio_close(upsfdtest); @@ -270,13 +272,13 @@ int main(int argc, char **argv) { } if(!strcmp(testType, "library")) { char chipNameLocal[NUT_GPIO_CHIPNAMEBUF]; - int expecting_failure; + int expecting_failure, failed; char subType[NUT_GPIO_SUBTYPEBUF]; fEof=fscanf(testData, "%d", &expecting_failure); fEof=fscanf(testData, "%s", chipNameLocal); fEof=fscanf(testData, "%s", subType); jmp_result = setjmp(env_buffer); - int failed=expecting_failure; + failed = expecting_failure; if(jmp_result) { /* test case exiting */ if(expecting_failure) failed=0; upsdrv_cleanup(); From 6f85a2e533e3a680c8163b99450566f46498969d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:09:06 +0200 Subject: [PATCH 1113/1232] scripts/systemd/nutshutdown.in: add copyright header, update practical comments Signed-off-by: Jim Klimov --- scripts/systemd/nutshutdown.in | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index ace2485b35..88c8464281 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -1,8 +1,33 @@ #!/bin/sh -# This script requires both nut-server (drivers) -# and nut-client (upsmon) to be present locally -# and on mounted filesystems +# Network UPS Tools (NUT) systemd-shutdown integration handler. +# +# NOTE: This script requires both nut-server package (or more specifically, +# the drivers for your device, which may be in further packages grouped +# by media/protocol and third-party dependencies), nut-client (upsmon), +# and their configuration files to be present locally and on still-mounted +# filesystems (may be read-only). +# +# Copyright (C) 2011-2023 by NUT contirbutors +# Michal Hlavinka, Arnaud Quette, Jim Klimov et al. +# +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ +# +# 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. + [ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || exit if @SBINDIR@/upsmon -K >/dev/null 2>&1; then From d8b49cfcda5652174213979df3d4e51eb0328e66 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:16:38 +0200 Subject: [PATCH 1114/1232] scripts/systemd/*.in: add short copyright header to unit files Signed-off-by: Jim Klimov --- configure.ac | 5 +++++ scripts/systemd/nut-driver-enumerator.path.in | 5 +++++ scripts/systemd/nut-driver-enumerator.service.in | 6 ++++++ scripts/systemd/nut-driver.target | 6 ++++++ scripts/systemd/nut-driver@.service.in | 6 ++++++ scripts/systemd/nut-monitor.service.in | 6 ++++++ scripts/systemd/nut-server.service.in | 6 ++++++ scripts/systemd/nut.target | 6 ++++++ 8 files changed, 46 insertions(+) diff --git a/configure.ac b/configure.ac index 10c9f16400..05cfc0d07a 100644 --- a/configure.ac +++ b/configure.ac @@ -4352,6 +4352,11 @@ dnl by "root:${RUN_AS_GROUP}" with 77x permissions. Is it safer?.. AS_IF([test -n "$systemdtmpfilesdir"], [mkdir -p "${TOP_BUILDDIR}"/scripts/systemd cat > "${TOP_BUILDDIR}"/scripts/systemd/nut-common-tmpfiles.conf.in << EOF +# Network UPS Tools (NUT) systemd integration +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + # See also: https://github.com/networkupstools/nut/wiki/Technicalities:-Work-with-PID-and-state-file-paths#pidpath-altpidpath-statepath # State file (e.g. upsd to driver pipes) and PID file location for NUT: d @STATEPATH@ 0770 @RUN_AS_USER@ @RUN_AS_GROUP@ - - diff --git a/scripts/systemd/nut-driver-enumerator.path.in b/scripts/systemd/nut-driver-enumerator.path.in index 11f340615a..620e1545f3 100644 --- a/scripts/systemd/nut-driver-enumerator.path.in +++ b/scripts/systemd/nut-driver-enumerator.path.in @@ -1,4 +1,9 @@ # Trigger restart of nut-driver-enumerator.service whenever ups.conf is edited +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ [Path] PathModified=@CONFPATH@/ups.conf diff --git a/scripts/systemd/nut-driver-enumerator.service.in b/scripts/systemd/nut-driver-enumerator.service.in index 7ede5a31d1..4e0a4709be 100644 --- a/scripts/systemd/nut-driver-enumerator.service.in +++ b/scripts/systemd/nut-driver-enumerator.service.in @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] # This unit starts early in system lifecycle to set up nut-driver instances. # End-user may also restart this unit after editing ups.conf to automatically diff --git a/scripts/systemd/nut-driver.target b/scripts/systemd/nut-driver.target index d994ab9882..0055e469d4 100644 --- a/scripts/systemd/nut-driver.target +++ b/scripts/systemd/nut-driver.target @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] Description=Network UPS Tools - target for power device drivers on this system After=local-fs.target diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in index b75e86a65e..1a1a04a4f0 100644 --- a/scripts/systemd/nut-driver@.service.in +++ b/scripts/systemd/nut-driver@.service.in @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] Description=Network UPS Tools - device driver for %I After=local-fs.target diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index e39064f690..25747fd30b 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] Description=Network UPS Tools - power device monitor and shutdown controller # Note: do not mistake this historic misnomer for "NUT-Monitor" Python GUI client diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 4c29561012..33f3b313d4 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] Description=Network UPS Tools - power devices information server After=local-fs.target network.target nut-driver.target diff --git a/scripts/systemd/nut.target b/scripts/systemd/nut.target index f744d29c55..3974fed4bf 100644 --- a/scripts/systemd/nut.target +++ b/scripts/systemd/nut.target @@ -1,3 +1,9 @@ +# Network UPS Tools (NUT) systemd integration +# Copyright (C) 2011-2023 by NUT contirbutors +# Distributed under the terms of GPLv2+ +# See https://networkupstools.org/ +# and https://github.com/networkupstools/nut/ + [Unit] Description=Network UPS Tools - target for power device drivers, data server and monitoring client (if enabled) on this system After=local-fs.target nut-driver.target nut-server.service nut-monitor.service From d13db31088e63010e1be615711cd84f02cecafef Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:18:14 +0200 Subject: [PATCH 1115/1232] fixup! scripts/systemd/nutshutdown.in: add copyright header, update practical comments Signed-off-by: Jim Klimov --- scripts/systemd/nutshutdown.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 88c8464281..7215a85409 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -9,7 +9,7 @@ # filesystems (may be read-only). # # Copyright (C) 2011-2023 by NUT contirbutors -# Michal Hlavinka, Arnaud Quette, Jim Klimov et al. +# Michal Hlavinka, Laurent Bigonville, Arnaud Quette, Jim Klimov et al. # # See https://networkupstools.org/ # and https://github.com/networkupstools/nut/ From 8e1dada58cfb26042be271948348dff8ee255ea5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:25:11 +0200 Subject: [PATCH 1116/1232] scripts/systemd/nutshutdown.in: update indentations and comments Signed-off-by: Jim Klimov --- scripts/systemd/nutshutdown.in | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 7215a85409..81c87be724 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -31,18 +31,25 @@ [ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || exit if @SBINDIR@/upsmon -K >/dev/null 2>&1; then - # The argument may be anything compatible with sleep - # (not necessarily a non-negative integer) - wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" + # The argument may be anything compatible with /bin/sleep + # (on OSes with systemd - assuming GNU coreutils or compatible, + # so not necessarily a non-negative integer) + wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" - @SBINDIR@/upsdrvctl shutdown + @SBINDIR@/upsdrvctl shutdown - if [ -n "$wait_delay" ] ; then - /bin/sleep $wait_delay - # We need to pass --force twice here to bypass systemd and execute the - # reboot directly ourself. - /bin/systemctl reboot --force --force - fi + if [ -n "$wait_delay" ] ; then + # Avoid the power-race condition (if wall power returned + # while we were shutting down, so some UPSes would not + # shutdown and/or powercycle the load as commanded above). + # Sleep "long enough" to drain the battery if the UPS is + # in fact on battery, or reboot if it became alive, so + # this computer is not in limbo forever. + /bin/sleep $wait_delay + # We need to pass --force twice here to bypass systemd + # and execute the reboot directly ourself. + /bin/systemctl reboot --force --force + fi fi exit 0 From 0523569fb85def8e7792e27004136f1995458a6f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:33:03 +0200 Subject: [PATCH 1117/1232] conf/nut.conf.sample: update existing comments Signed-off-by: Jim Klimov --- conf/nut.conf.sample | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index ebf6c04b96..3607857bbb 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -1,19 +1,28 @@ # Network UPS Tools: example nut.conf # +# This file tries to standardize the various files being found in the field, +# like /etc/default/nut on Debian based systems, /etc/sysconfig/ups on RedHat +# based systems, ... Distribution's init script or service unit/method script +# should source this file to see which component(s) has to be started. +# Some scripts and units provided by NUT project itself may also look into +# this file for optional configuration about OS integration. +# +# IMPORTANT NOTES: +# This file is intended to be sourced by standard POSIX shell scripts +# (so there is no guaranteed `export VAR=VAL` syntax) and additionally +# by systemd on Linux (no guaranteed expansion of variables). +# You MUST NOT use spaces around the equal sign! +# ############################################################################## # General section ############################################################################## # The MODE determines which part of the NUT is to be started, and which # configuration files must be modified. # -# This file try to standardize the various files being found in the field, like -# /etc/default/nut on Debian based systems, /etc/sysconfig/ups on RedHat based -# systems, ... Distribution's init script should source this file to see which -# component(s) has to be started. -# # The values of MODE can be: # - none: NUT is not configured, or use the Integrated Power Management, or use -# some external system to startup NUT components. So nothing is to be started. +# some external system to startup NUT components. So nothing is to be started +# by scripts or services bundled with NUT packages. # - standalone: This mode address a local only configuration, with 1 UPS # protecting the local system. This implies to start the 3 NUT layers (driver, # upsd and upsmon) and the matching configuration files. This mode can also @@ -23,12 +32,9 @@ # specific LISTEN directive in upsd.conf. # Since this MODE is opened to the network, a special care should be applied # to security concerns. -# - netclient: this mode only requires upsmon. -# -# IMPORTANT NOTE: -# This file is intended to be sourced by standard POSIX shell scripts (so -# there is no guaranteed `export VAR=VAL` syntax) and by systemd on Linux. -# You MUST NOT use spaces around the equal sign! +# - netclient: this mode only requires upsmon (and tools it may be using, like +# upssched or custom scripts) to monitor a remote NUT server and possibly +# shut down this system (part of upsmon must run as root then). MODE=none From 4cc756d414e82dd968e2ce4d749a811ead5d0f63 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 13:39:49 +0200 Subject: [PATCH 1118/1232] conf/nut.conf.sample: refer to `man nut.conf` for more info Signed-off-by: Jim Klimov --- conf/nut.conf.sample | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index 3607857bbb..8950728851 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -13,6 +13,9 @@ # by systemd on Linux (no guaranteed expansion of variables). # You MUST NOT use spaces around the equal sign! # +# See also: `man nut.conf` (usually in Manual pages Section 5, +# for Configuration files) +# ############################################################################## # General section ############################################################################## From 435a1e186f28ec1b1093f5bcbc52c1fa8e43b46d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 14:12:59 +0200 Subject: [PATCH 1119/1232] fixup! conf/nut.conf.sample: update existing comments Signed-off-by: Jim Klimov --- conf/nut.conf.sample | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index 8950728851..009828b8ef 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -12,6 +12,8 @@ # (so there is no guaranteed `export VAR=VAL` syntax) and additionally # by systemd on Linux (no guaranteed expansion of variables). # You MUST NOT use spaces around the equal sign! +# Practical support for this file and its settings currently varies between +# various OS packages and NUT sample scripts, but should converge over time. # # See also: `man nut.conf` (usually in Manual pages Section 5, # for Configuration files) From a7f88889d3b5ce3106176e0b54dbef005a653d5b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 14:13:27 +0200 Subject: [PATCH 1120/1232] conf/nut.conf.sample: document other options currently highlighted in the man page Signed-off-by: Jim Klimov --- conf/nut.conf.sample | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index 009828b8ef..b9ffb9041a 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -43,8 +43,29 @@ MODE=none -# Uncomment this to allow starting the service even if ups.conf has no device -# sections at the moment. This environment variable overrides the built-in -# "false" and an optional same-named default flag that can be set in upsd.conf: +# Uncomment this to allow starting the service even if `ups.conf` has no device +# sections configured at the moment. This environment variable overrides the +# built-in "false" flag in `upsd`, and an optional same-named default flag that +# can be set in `upsd.conf`. If you want a data server always running, even if +# it initially has nothing to serve (may be live-reloaded later, when devices +# become configured), this option is for you. #ALLOW_NO_DEVICE=true #export ALLOW_NO_DEVICE + +# The optional 'UPSD_OPTIONS' allow to set upsd specific command-line options. +# It is ignored when 'MODE' above indicates that no upsd should be running. +# It may be redundant in comparison to options which can be set in `upsd.conf`. +#UPSD_OPTIONS= + +# The optional 'UPSMON_OPTIONS' allow to set upsmon specific command-line options. +# It is ignored when 'MODE' above indicates that no upsmon should be running. +# It may be redundant in comparison to options which can be set in `upsmon.conf`. +#UPSMON_OPTIONS= + +# If the optional 'POWEROFF_WAIT' is configured (to a value that can be handled +# by `/bin/sleep` on the current system - typically an integer with the number +# of seconds for a delay, but not always limited to that syntax), and the current +# system which manages one or more UPS devices would not only command it to shut +# down, but also try to avoid the "Power race". Caveats emptor, see NUT FAQ and +# other docs for details. +#POWEROFF_WAIT=3600 From 246fce1916abe01462fe2c32d4bbf589fdbd87ff Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 14:16:25 +0200 Subject: [PATCH 1121/1232] docs/man/nut.conf.txt: document ALLOW_NO_DEVICE setting Signed-off-by: Jim Klimov --- docs/man/nut.conf.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/man/nut.conf.txt b/docs/man/nut.conf.txt index 0d4930520f..83563f3fd4 100644 --- a/docs/man/nut.conf.txt +++ b/docs/man/nut.conf.txt @@ -54,6 +54,17 @@ netclient;; When only upsmon is required, possibly because there are other hosts that are more closely attached to the UPS, the MODE should be set to netclient. +*ALLOW_NO_DEVICE*:: +Optional, defaults to `false`. Set this to `true` to allow starting the `upsd` +NUT data server service even if `ups.conf` has no device sections configured +at the moment. This environment variable overrides the built-in "false" flag +value in the `upsd` program, and an optional same-named default flag that +can be set in `upsd.conf`. ++ +If you want a data server always running and responding on the network, even +if it initially has nothing to serve (may be live-reloaded later, when devices +become configured), this option is for you. + *UPSD_OPTIONS*:: Optional. Set upsd specific options. See linkman:upsd[8] for more details. It is ignored when 'MODE' above indicates that no upsd From edc83de43fb827aa7fdaf297429cfca37cca57bc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Oct 2023 14:25:42 +0200 Subject: [PATCH 1122/1232] Introduce POWEROFF_QUIET for nutshutdown et al Signed-off-by: Jim Klimov --- conf/nut.conf.sample | 7 +++++++ docs/man/nut.conf.txt | 9 ++++++++- docs/nut.dict | 3 ++- scripts/systemd/nutshutdown.in | 19 ++++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index b9ffb9041a..4cd84dd054 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -69,3 +69,10 @@ MODE=none # down, but also try to avoid the "Power race". Caveats emptor, see NUT FAQ and # other docs for details. #POWEROFF_WAIT=3600 + +# The optional 'POWEROFF_QUIET' setting controls if the NUT shutdown integration +# scripts or service units would emit messages about their activity (or lack +# thereof). By default they may be verbose, to aid post-mortem troubleshooting +# via logs or console captures. +# Set to `true` to avoid that trove of information, if you consider it noise. +#POWEROFF_QUIET=true diff --git a/docs/man/nut.conf.txt b/docs/man/nut.conf.txt index 83563f3fd4..182f04cd01 100644 --- a/docs/man/nut.conf.txt +++ b/docs/man/nut.conf.txt @@ -87,10 +87,17 @@ unavailable. On the other hand, it should not be so long that the system remains offline for an unreasonable amount of time if line power has returned. See sleep(1) for compatible time syntax. If you specify the time in seconds, use the "s" suffix. - ++ WARNING: this workaround might be dangerous under some circumstances. Please read http://bugs.debian.org/358696 for more details. +*POWEROFF_QUIET*:: +Optional, defaults to `false`. This setting controls if the NUT shutdown +integration scripts or service units would emit messages about their activity +(or lack thereof). By default they may be verbose, to aid in post-mortem +troubleshooting via logs or console captures. Set to `true` to avoid that +trove of information, if you consider it noise. + EXAMPLE ------- diff --git a/docs/nut.dict b/docs/nut.dict index 46ee7ef0fc..a836f1cc99 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3238 utf-8 +personal_ws-1.1 en 3239 utf-8 AAS ABI ACFAIL @@ -2393,6 +2393,7 @@ monpasswd monslave monuser morbo +mortem mozilla msec msg diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 81c87be724..5965b054c4 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -28,7 +28,14 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -[ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || exit +POWEROFF_QUIET="`/bin/sed -ne 's#^ *POWEROFF_QUIET= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" \ +&& [ x"${POWEROFF_QUIET-}" = xtrue ] \ +|| POWEROFF_QUIET="false" + +[ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || { + $POWEROFF_QUIET || echo "$0: SKIP: could not locate '@SBINDIR@/upsmon' and/or '@SBINDIR@/upsdrvctl'" >&2 + exit 1 +} if @SBINDIR@/upsmon -K >/dev/null 2>&1; then # The argument may be anything compatible with /bin/sleep @@ -36,6 +43,7 @@ if @SBINDIR@/upsmon -K >/dev/null 2>&1; then # so not necessarily a non-negative integer) wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" + $POWEROFF_QUIET || echo "$0: Commanding UPSes (if any) to shutdown" >&2 @SBINDIR@/upsdrvctl shutdown if [ -n "$wait_delay" ] ; then @@ -45,11 +53,20 @@ if @SBINDIR@/upsmon -K >/dev/null 2>&1; then # Sleep "long enough" to drain the battery if the UPS is # in fact on battery, or reboot if it became alive, so # this computer is not in limbo forever. + $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleeping $wait_delay" >&2 + /bin/sleep $wait_delay + + $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleep finished, rebooting..." >&2 + # We need to pass --force twice here to bypass systemd # and execute the reboot directly ourself. /bin/systemctl reboot --force --force + else + $POWEROFF_QUIET || echo "$0: Power-race avoidance: POWEROFF_WAIT is not configured at this time, proceeding to shutdown" >&2 fi +else + $POWEROFF_QUIET || echo "$0: SKIP: Not in FSD (killpower) mode at this time" >&2 fi exit 0 From c189938c6f66aa7f01da5957210478fd7885d6da Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 03:19:47 +0200 Subject: [PATCH 1123/1232] scripts/systemd/nutshutdown.in: make it useful for NUT clients (which shut down and may want to avoid power races) Signed-off-by: Jim Klimov --- scripts/systemd/nutshutdown.in | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 5965b054c4..78a16db4a2 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -32,19 +32,26 @@ POWEROFF_QUIET="`/bin/sed -ne 's#^ *POWEROFF_QUIET= *\(.*\)$#\1#p' @CONFPATH@/nu && [ x"${POWEROFF_QUIET-}" = xtrue ] \ || POWEROFF_QUIET="false" -[ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || { - $POWEROFF_QUIET || echo "$0: SKIP: could not locate '@SBINDIR@/upsmon' and/or '@SBINDIR@/upsdrvctl'" >&2 +[ -x "@SBINDIR@/upsmon" ] || { + $POWEROFF_QUIET || echo "$0: SKIP: could not locate '@SBINDIR@/upsmon''" >&2 exit 1 } +# Will at most run the optional power-race avoidance sleep part +[ -x "@SBINDIR@/upsdrvctl" ] || { + $POWEROFF_QUIET || echo "$0: WARNING: could not locate '@SBINDIR@/upsdrvctl' - will not command any UPS devices to shut down" >&2 +} + if @SBINDIR@/upsmon -K >/dev/null 2>&1; then # The argument may be anything compatible with /bin/sleep # (on OSes with systemd - assuming GNU coreutils or compatible, # so not necessarily a non-negative integer) wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" - $POWEROFF_QUIET || echo "$0: Commanding UPSes (if any) to shutdown" >&2 - @SBINDIR@/upsdrvctl shutdown + if [ -x "@SBINDIR@/upsdrvctl" ] ; then + $POWEROFF_QUIET || echo "$0: Commanding UPSes (if any) to shutdown" >&2 + @SBINDIR@/upsdrvctl shutdown || echo "$0: Something failed about UPS shutdown commands" >&2 + fi if [ -n "$wait_delay" ] ; then # Avoid the power-race condition (if wall power returned From 85a56dcbc1f14cea2a1d75a6d2e254fffb247656 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 03:44:51 +0200 Subject: [PATCH 1124/1232] scripts/systemd/nutshutdown.in: simplify with sourcing of the optional config file --- scripts/systemd/nutshutdown.in | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 78a16db4a2..2bd09710b7 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -28,8 +28,11 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -POWEROFF_QUIET="`/bin/sed -ne 's#^ *POWEROFF_QUIET= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" \ -&& [ x"${POWEROFF_QUIET-}" = xtrue ] \ +if [ -s "@CONFPATH@/nut.conf" ]; then + . "@CONFPATH@/nut.conf" || true +fi + +[ x"${POWEROFF_QUIET-}" = xtrue ] \ || POWEROFF_QUIET="false" [ -x "@SBINDIR@/upsmon" ] || { @@ -43,26 +46,24 @@ POWEROFF_QUIET="`/bin/sed -ne 's#^ *POWEROFF_QUIET= *\(.*\)$#\1#p' @CONFPATH@/nu } if @SBINDIR@/upsmon -K >/dev/null 2>&1; then - # The argument may be anything compatible with /bin/sleep - # (on OSes with systemd - assuming GNU coreutils or compatible, - # so not necessarily a non-negative integer) - wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" - if [ -x "@SBINDIR@/upsdrvctl" ] ; then $POWEROFF_QUIET || echo "$0: Commanding UPSes (if any) to shutdown" >&2 @SBINDIR@/upsdrvctl shutdown || echo "$0: Something failed about UPS shutdown commands" >&2 fi - if [ -n "$wait_delay" ] ; then + if [ -n "$POWEROFF_WAIT" ] ; then # Avoid the power-race condition (if wall power returned # while we were shutting down, so some UPSes would not # shutdown and/or powercycle the load as commanded above). # Sleep "long enough" to drain the battery if the UPS is # in fact on battery, or reboot if it became alive, so # this computer is not in limbo forever. - $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleeping $wait_delay" >&2 + $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleeping $POWEROFF_WAIT" >&2 - /bin/sleep $wait_delay + # The argument may be anything compatible with /bin/sleep + # (on OSes with systemd - assuming GNU coreutils or compatible, + # so not necessarily a non-negative integer) + /bin/sleep $POWEROFF_WAIT $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleep finished, rebooting..." >&2 From e214a008768674bf8eb341705106cace944444ea Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 15:35:00 +0200 Subject: [PATCH 1125/1232] docs/Makefile.am: avoid defining "check-local" target twice to include optional "spellcheck", not all tools like that [#2081] Signed-off-by: Jim Klimov --- docs/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 4f234e6a54..41a0864f63 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -87,7 +87,11 @@ SUFFIXES = .txt .html .pdf -spellchecked all: doc # This list is defined by configure script choices and options: -check-local: @DOC_CHECK_LIST@ +CHECK_LOCAL_TARGETS = @DOC_CHECK_LIST@ +if WITH_SPELLCHECK +CHECK_LOCAL_TARGETS += spellcheck +endif WITH_SPELLCHECK +check-local: $(CHECK_LOCAL_TARGETS) # This list is defined by configure script choices and options: doc: @DOC_BUILD_LIST@ @@ -499,10 +503,6 @@ spellcheck-interactive: echo "because other systems might not know these words in their system dictionaries)"; \ echo "------------------------------------------------------------------------" -if WITH_SPELLCHECK -check-local: spellcheck -endif WITH_SPELLCHECK - else !HAVE_ASPELL # This rule woulf probably just fail; normally with no ASPELL there are no callers for it */*-spellchecked *-spellchecked: Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) From 5b23cc2de727b5808d559ed0234d9f12d95b403a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 09:35:27 +0200 Subject: [PATCH 1126/1232] docs/nut.dict: update for nut-website additions Signed-off-by: Jim Klimov --- docs/nut.dict | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 46ee7ef0fc..e0462fbfa7 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3238 utf-8 +personal_ws-1.1 en 3241 utf-8 AAS ABI ACFAIL @@ -671,6 +671,7 @@ MONITORed MOXA MPSU MQ +MQTT MSI MSII MSIII @@ -735,6 +736,7 @@ Mozilla Msg MultiLink Multiplug +Munin MyCompany MyPasSw MySQL @@ -2394,6 +2396,7 @@ monslave monuser morbo mozilla +mqtt msec msg msgfmt From 6fa17d8018d0373b95d91400e1c09bcbc021735c Mon Sep 17 00:00:00 2001 From: Axel Gembe Date: Wed, 4 Oct 2023 16:02:11 +0700 Subject: [PATCH 1127/1232] configure.ac: Fix out of source tree builds The code to detect the available drivers does so by parsing `Makefile.am` but it does not do so relative to "$srcdir" so trying to do a configure outside of the source directory will fail. Signed-off-by: Axel Gembe --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 10c9f16400..f8a3e21e51 100644 --- a/configure.ac +++ b/configure.ac @@ -1273,7 +1273,7 @@ AC_ARG_WITH(drivers, SPACE="`printf "$LB"' \t'"$RB"`" SPACES="${SPACE}*" sed -e "s/${SPACES}""$LB"'+'"$RB"'*='"${SPACES}/=/" \ - -e "s/^${SPACES}//" < drivers/Makefile.am \ + -e "s/^${SPACES}//" < "$srcdir/drivers/Makefile.am" \ | { C=false; V=false while read LINE ; do From 33bda61aa572b6d09ba077e0a560da0fcae8f8f8 Mon Sep 17 00:00:00 2001 From: moonbuggy <3319867+moonbuggy@users.noreply.github.com> Date: Wed, 4 Oct 2023 21:50:20 +1100 Subject: [PATCH 1128/1232] correct voltages for Opti-UPS 230V AC models; correct battery capacity for 24V models Signed-off-by: moonbuggy <3319867+moonbuggy@users.noreply.github.com> --- drivers/optiups.c | 58 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/optiups.c b/drivers/optiups.c index eddd94e173..4814b48af9 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -28,7 +28,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Opti-UPS driver" -#define DRIVER_VERSION "1.03" +#define DRIVER_VERSION "1.04" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -83,7 +83,8 @@ static char _buf[256]; static int optimodel = 0; enum { OPTIMODEL_DEFAULT = 0, - OPTIMODEL_ZINTO = 1 + OPTIMODEL_ZINTO = 1, + OPTIMODEL_PS = 2 }; @@ -123,6 +124,19 @@ static ezfill_t _pollv_zinto[] = { { "BT", "ups.temperature", 0 }, }; +/* When on a 220-2400V mains supply, the NV and OV commands return 115V values. FV + * returns a value that matches the DIP switch settings for 120/240V models, so + * it can be used to scale the valus from NV and OV. + * + * I suspect this will be the case for other Opti-UPS models, but as I can only + * test with a PS-1440RM at 230V the change is only applied to PowerSeries models. + */ +static ezfill_t _pollv_ps[] = { + { "OL", "ups.load", 1.0 }, + { "FF", "input.frequency", 0.1 }, + { "BT", "ups.temperature", 0 }, +}; + /* model "IO" is parsed differently in upsdrv_initinfo() */ static ezfill_t _initv[] = { { "IM", "ups.mfr", 0 }, @@ -347,6 +361,13 @@ void upsdrv_initinfo(void) optiquery( "ON" ); } + /* Autodetect an Opti-UPS PS series */ + r = optiquery( "IO" ); + if ( r > 0 && !strncasecmp(_buf, "PS-", 3) ) + { + optimodel = OPTIMODEL_PS; + } + optifill( _initv, sizeof(_initv)/sizeof(_initv[0]) ); /* Parse out model into longer string -- is this really USEFUL??? */ @@ -463,6 +484,27 @@ void upsdrv_updateinfo(void) /* read some easy settings */ if ( optimodel == OPTIMODEL_ZINTO ) optifill( _pollv_zinto, sizeof(_pollv_zinto)/sizeof(_pollv_zinto[0]) ); + else if ( optimodel == OPTIMODEL_PS ) { + optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) ); + + r = optiquery( "NV" ); + float inV = strtol ( _buf, NULL, 10); + r = optiquery( "OV" ); + float outV = strtol ( _buf, NULL, 10); + + r = optiquery( "FV" ); + if ( r >= 1 ) + { + float f = strtol ( _buf, NULL, 10 ); + if ( f > 180 ) + { + inV = inV * 2; + outV = outV * 2; + } + } + dstate_setinfo( "input.voltage", "%.1f", inV ); + dstate_setinfo( "output.voltage", "%.1f", outV ); + } else optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) ); @@ -475,8 +517,16 @@ void upsdrv_updateinfo(void) float p, v = strtol( _buf, NULL, 10 ) / 10.0; dstate_setinfo("battery.voltage", "%.1f", v ); - /* battery voltage range: 10.4 - 13.0 VDC */ - p = ((v - 10.4) / 2.6) * 100.0; + if (v > 20) + { + /* battery voltage range: 20.8 - 26.0 VDC */ + p = ((v - 20.8) / 5.2) * 100.0; + } + else + { + /* battery voltage range: 10.4 - 13.0 VDC */ + p = ((v - 10.4) / 2.6) * 100.0; + } if ( p > 100.0 ) p = 100.0; dstate_setinfo("battery.charge", "%.1f", p ); From 317df5c2035fef6c0c191517005783334e5d4c7f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Oct 2023 14:50:56 +0200 Subject: [PATCH 1129/1232] scripts/systemd/nutshutdown.in: also log critical progress messages to /dev/console if available (and not-quiet mode) Signed-off-by: Jim Klimov --- scripts/systemd/nutshutdown.in | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in index 2bd09710b7..8625e167d9 100755 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -47,7 +47,10 @@ fi if @SBINDIR@/upsmon -K >/dev/null 2>&1; then if [ -x "@SBINDIR@/upsdrvctl" ] ; then - $POWEROFF_QUIET || echo "$0: Commanding UPSes (if any) to shutdown" >&2 + $POWEROFF_QUIET || { + echo "$0: Commanding UPSes (if any) to shutdown" >&2 + [ -w /dev/console ] && echo "`TZ=UTC LANG=C date`: $0: Commanding UPSes (if any) to shutdown" >/dev/console || true + } @SBINDIR@/upsdrvctl shutdown || echo "$0: Something failed about UPS shutdown commands" >&2 fi @@ -58,14 +61,20 @@ if @SBINDIR@/upsmon -K >/dev/null 2>&1; then # Sleep "long enough" to drain the battery if the UPS is # in fact on battery, or reboot if it became alive, so # this computer is not in limbo forever. - $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleeping $POWEROFF_WAIT" >&2 + $POWEROFF_QUIET || { + echo "$0: Power-race avoidance: sleeping $POWEROFF_WAIT" >&2 + [ -w /dev/console ] && echo "`TZ=UTC LANG=C date`: $0: Power-race avoidance: sleeping $POWEROFF_WAIT" >/dev/console || true + } # The argument may be anything compatible with /bin/sleep # (on OSes with systemd - assuming GNU coreutils or compatible, # so not necessarily a non-negative integer) /bin/sleep $POWEROFF_WAIT - $POWEROFF_QUIET || echo "$0: Power-race avoidance: sleep finished, rebooting..." >&2 + $POWEROFF_QUIET || { + echo "$0: Power-race avoidance: sleep finished, rebooting..." >&2 + [ -w /dev/console ] && echo "`TZ=UTC LANG=C date`: $0: Power-race avoidance: sleep finished, rebooting..." >/dev/console || true + } # We need to pass --force twice here to bypass systemd # and execute the reboot directly ourself. From ebf3105f986221b70f468e7b7d3cc2b01bf41503 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Oct 2023 16:01:53 +0200 Subject: [PATCH 1130/1232] docs/configure.txt: document --libexecdir Signed-off-by: Jim Klimov --- docs/configure.txt | 11 +++++++++++ docs/nut.dict | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/configure.txt b/docs/configure.txt index 9ff3d2bba9..81aef71408 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -631,6 +631,17 @@ configuration, this can include the `libupsclient`, `libnutclient`, `libnutclientsub`, `libnutscan` and their pkg-config metadata (see `--with-pkgconfig-dir` option). The default is `/lib`. + --libexecdir=PATH + +Sets the installation path for "executable libraries" -- helper scripts +or programs that are not intended for direct and regular use by people, +and rather are implementation details of services. Depending on the +build configuration, this can include the `nut-driver-enumerator.sh`, +`sockdebug`, and others. The default is `/libexec`. + +Package distributions may want to use this option to customize this path +to include the package name, e.g. set it to `/libexec/nut`. + --with-pkgconfig-dir=PATH Where to install pkg-config `*.pc` files. This option only has an diff --git a/docs/nut.dict b/docs/nut.dict index f94a80a4af..d907cce2cb 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3242 utf-8 +personal_ws-1.1 en 3243 utf-8 AAS ABI ACFAIL @@ -2224,6 +2224,7 @@ libcurl libdir libdummy libexec +libexecdir libfreeipmi libgd libgpgme From 2918f0ae81b32c125cd93a7d6b12907fc5072857 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Oct 2023 16:15:47 +0200 Subject: [PATCH 1131/1232] clients/Makefile.am: refactor definitions of LDADD_FULL and LDADD_CLIENT for easier reuse upsmon is a daemon with systemd notify among other things, and uses the full libcommon upssched should suffice with the client version Signed-off-by: Jim Klimov --- clients/Makefile.am | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/clients/Makefile.am b/clients/Makefile.am index d38a6a5bf2..8d88eba14c 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -12,13 +12,20 @@ $(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libparseconf.la: dummy @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) -# by default, link programs in this directory with -# the more compact libcommonclient.a bundle -LDADD = $(top_builddir)/common/libcommonclient.la libupsclient.la $(NETLIBS) +LDADD_FULL = $(top_builddir)/common/libcommon.la libupsclient.la $(NETLIBS) +if WITH_SSL + LDADD_FULL += $(LIBSSL_LIBS) +endif + +LDADD_CLIENT = $(top_builddir)/common/libcommonclient.la libupsclient.la $(NETLIBS) if WITH_SSL - LDADD += $(LIBSSL_LIBS) + LDADD_CLIENT += $(LIBSSL_LIBS) endif +# by default, link programs in this directory with +# the more compact libcommonclient.a bundle +LDADD = $(LDADD_CLIENT) + # Avoid per-target CFLAGS, because this will prevent re-use of object # files. In any case, CFLAGS are only -I options, so there is no harm, # but only add them if we really use the target. @@ -62,12 +69,13 @@ upscmd_SOURCES = upscmd.c upsclient.h upsrw_SOURCES = upsrw.c upsclient.h upslog_SOURCES = upslog.c upsclient.h upslog.h upsmon_SOURCES = upsmon.c upsmon.h upsclient.h +upsmon_LDADD = $(LDADD_FULL) if HAVE_WINDOWS_SOCKETS message_SOURCES = message.c endif upssched_SOURCES = upssched.c upssched.h -upssched_LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la $(NETLIBS) +upssched_LDADD = $(top_builddir)/common/libcommonclient.la $(top_builddir)/common/libparseconf.la $(NETLIBS) upsimage_cgi_SOURCES = upsimage.c upsclient.h upsimagearg.h cgilib.c cgilib.h upsimage_cgi_LDADD = $(LDADD) $(LIBGD_LDFLAGS) From 12f76f6d702b43776176400d41989438c1af8f2b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Oct 2023 16:19:46 +0200 Subject: [PATCH 1132/1232] common/common.c: upsnotify(): make first/only notification faults visible They can be important for troubleshooting, e.g. services that rely on sd_notify() but never get the READY message would loop in restarts. Signed-off-by: Jim Klimov --- common/common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/common.c b/common/common.c index 85d42973fc..89991619cb 100644 --- a/common/common.c +++ b/common/common.c @@ -832,14 +832,14 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) NUT_UNUSED_VARIABLE(buf); NUT_UNUSED_VARIABLE(msglen); if (!upsnotify_reported_disabled_systemd) - upsdebugx(6, "%s: notify about state %i with libsystemd: " + upsdebugx(0, "%s: notify about state %i with libsystemd: " "skipped for libcommonclient build, " "will not spam more about it", __func__, state); upsnotify_reported_disabled_systemd = 1; # else if (!getenv("NOTIFY_SOCKET")) { if (!upsnotify_reported_disabled_systemd) - upsdebugx(6, "%s: notify about state %i with libsystemd: " + upsdebugx(0, "%s: notify about state %i with libsystemd: " "was requested, but not running as a service unit now, " "will not spam more about it", __func__, state); @@ -1110,7 +1110,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) ) { if (ret == -127) { if (!upsnotify_reported_disabled_notech) - upsdebugx(6, "%s: failed to notify about state %i: no notification tech defined, will not spam more about it", __func__, state); + upsdebugx(0, "%s: failed to notify about state %i: no notification tech defined, will not spam more about it", __func__, state); upsnotify_reported_disabled_notech = 1; } else { upsdebugx(6, "%s: failed to notify about state %i", __func__, state); @@ -1120,7 +1120,7 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) #if defined(WITH_LIBSYSTEMD) && (WITH_LIBSYSTEMD) # if ! DEBUG_SYSTEMD_WATCHDOG if (state == NOTIFY_STATE_WATCHDOG && !upsnotify_reported_watchdog_systemd) { - upsdebugx(6, "%s: logged the systemd watchdog situation once, will not spam more about it", __func__); + upsdebugx(0, "%s: logged the systemd watchdog situation once, will not spam more about it", __func__); upsnotify_reported_watchdog_systemd = 1; } # endif From 14f6dd1d442c5b1839cb3a212398677dadf33e30 Mon Sep 17 00:00:00 2001 From: moonbuggy <3319867+moonbuggy@users.noreply.github.com> Date: Thu, 5 Oct 2023 04:00:52 +1100 Subject: [PATCH 1133/1232] updated driver.list.in Signed-off-by: moonbuggy <3319867+moonbuggy@users.noreply.github.com> --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index ac613778c6..d1eb3951e2 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -925,6 +925,7 @@ "Opti-UPS" "ups" "1" "PowerES" "420E" "optiups" "Opti-UPS" "ups" "1" "VS 575C" "type=OPTI" "powercom" "Opti-UPS" "ups" "1" "Power Series" "PS1500E" "blazer_usb" +"Opti-UPS" "ups" "1" "Power Series" "PS1440RM" "optiups" "Orvaldi Power Protection" "ups" "2" "various" "not 400 or 600" "blazer_ser" "Orvaldi Power Protection" "ups" "2" "750 / 900SP" "USB" "blazer_usb" From 72d2b18600c92306e419e164a1d3849bac331ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20W=20Baul=C3=A9?= Date: Wed, 4 Oct 2023 15:36:17 -0300 Subject: [PATCH 1134/1232] add support to SMS 1phase brazil from #1987 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested on Nobreak SMS PREMIUM 1500 VA (with WiFi) and M3 Senoidal. Signed-off-by: Alex W Baulé --- docs/sms-brazil-protocol.txt | 346 +++++++++++++++++ drivers/Makefile.am | 4 +- drivers/sms_ser.c | 693 +++++++++++++++++++++++++++++++++++ drivers/sms_ser.h | 73 ++++ 4 files changed, 1115 insertions(+), 1 deletion(-) create mode 100644 docs/sms-brazil-protocol.txt create mode 100644 drivers/sms_ser.c create mode 100644 drivers/sms_ser.h diff --git a/docs/sms-brazil-protocol.txt b/docs/sms-brazil-protocol.txt new file mode 100644 index 0000000000..1093304b08 --- /dev/null +++ b/docs/sms-brazil-protocol.txt @@ -0,0 +1,346 @@ +SMS Brazil Protocols +==================== + +Using the PowerView as source, there is a folder, called `protocols` inside the installed directory, e.g. `"C:\Alerta24h\SMS_Power_View\resource"`. There are 4 protocol files (`monofasico.xml`, `trifasico.xml`, `upsilon.xml` and `voltronic.xml`), and one file called `verificaProtocolo.xml`. + +The file `verificaProtocolo.xml` has serial/USB commands to be sent, to detect the UPS device. + +The file contents are: + +.verificaProtocolo.xml +[source,xml] +---- + + + + + QSG + isNobreakVoltronic + Resgata medidores e status do UPS + + + + + + + + + + + + + + + + G1 + isNobreakTrifasico + Detecta se o no-break é trifásico + + + + + + + + + + + + + + + + + I + isNobreakMonofasico + Detecta se o no-break é monofásico + + + + + + + + + + + + + + + + + Q1 + isNobreakSinusTriad + Resgata medidores e status do UPS + + + + + + + + + + + + + +---- + +In the `sms_ser.c` and `sms_ser.h` there is only the `monofasico.xml` implementation, because is describes my UPS and I can implement and validate it. But it is totally valid if someone has another SMS_Brazil UPS and wanted to include another protocol, you can send me an email (looking in the `sms_ser.h` source to get it). + +Here is the `monofasico.xml` protocol: + +.monofasico.xml +[source,xml] +---- + + + + + Q + MedidoresEstado + Resgata medidores e status do UPS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Q + MedidoresEstadoDefault + Resgata um bean com os valores pré-definidos para os medidores e status do UPS + + + + + + + + + + + + + + + + + + + + + + + I + Informacoes + Resgata informações do UPS + + + + + + + + + + + + + + + + + + + + I + InformacoesDefault + Resgata informações do UPS + The + + + + + + + F + Caracteristicas + Resgata características do UPS + + + + + + + + + + + + + + + + + + + + + F + CaracteristicasDefault + Resgata características default do UPS + + + + + + + + + + + + M + MudaBeep + Muda o beep + + + + + + + + + + + + + L + TesteBateriaBaixa + Teste até bateria baixa + + + + + + + + + + + + + T + TestePorSegundos + Teste por 'n' segundos + + + + + + + + + + + + + S + ShutdownPorSegundos + Shutdown em n segundos + + + + + + + + + + + + + R + ShutdownRestore + Shutdown e restore + + + + + + + + + + + + + D + CancelarTeste + Cancelamento de Teste + + + + + + + + + + + + + C + CancelarShutdownRestore + Cancelamento de Shutdown ou restore + + + + + + + + + + + +---- diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 1a576f944b..1f99c802e4 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -48,7 +48,7 @@ SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ gamatronic genericups isbmex liebert liebert-esp2 masterguard metasys \ mge-utalk microdowell microsol-apc mge-shut oneac optiups powercom rhino \ safenet nutdrv_siemens-sitop solis tripplite tripplitesu upscode2 victronups powerpanel \ - blazer_ser ivtscd apcsmart apcsmart-old riello_ser + blazer_ser ivtscd apcsmart apcsmart-old riello_ser sms_ser SNMP_DRIVERLIST = snmp-ups USB_LIBUSB_DRIVERLIST = usbhid-ups bcmxcp_usb tripplite_usb \ blazer_usb richcomm_usb riello_usb \ @@ -175,6 +175,8 @@ upscode2_LDADD = $(LDADD) -lm victronups_SOURCES = victronups.c riello_ser_SOURCES = riello.c riello_ser.c riello_ser_LDADD = $(LDADD) -lm +sms_ser_SOURCES = sms_ser.c +sms_ser_LDADD = $(LDADD) -lm # non-serial drivers: these use custom LDADD and/or CFLAGS diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c new file mode 100644 index 0000000000..04ae728c81 --- /dev/null +++ b/drivers/sms_ser.c @@ -0,0 +1,693 @@ +/* + * sms_ser.c: code for mono protocol for SMS Brazil UPSes + * + * Copyright (C) 2023 - Alex W. Baule + * + * 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 + * + * Reference of the derivative work: riello driver + */ + +#include "config.h" /* must be the first header */ +#include + +#include "common.h" /* for upsdebugx() etc */ +#include "sms_ser.h" +#include "main.h" +#include "serial.h" + +#define ENDCHAR '\r' + +#define DRIVER_NAME "SMS Brazil UPS driver" +#define DRIVER_VERSION "1.00" + +#define QUERY_SIZE 7 +#define BUFFER_SIZE 18 +#define RESULT_SIZE 18 +#define HUMAN_VALUES 7 + +static unsigned int bootdelay = DEFAULT_BOOTDELAY; +static uint8_t bufOut[BUFFER_SIZE]; +static uint8_t bufIn[BUFFER_SIZE]; +static SmsData DeviceData; + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Alex W. Baulé ", + DRV_BETA, + {NULL}}; + +void sms_parse_features(uint8_t *rawvalues, SmsData *results) { + char tbattery[6]; + char frequency[4]; + + memset(results->voltageRange, 0, sizeof(results->voltageRange)); + memset(results->currentRange, 0, sizeof(results->currentRange)); + memset(tbattery, 0, sizeof(tbattery)); + memset(frequency, 0, sizeof(frequency)); + + for (int i = 1; i < BUFFER_SIZE - 2; i++) { + if (i <= 7) { + snprintfcat(results->voltageRange, 14, "%c", rawvalues[i]); + } else if (i <= 10) { + snprintfcat(results->currentRange, 6, "%c", rawvalues[i]); + } else if (i <= 13) { + snprintfcat(tbattery, sizeof(tbattery), "%c", rawvalues[i]); + } else { + snprintfcat(frequency, sizeof(frequency), "%c", rawvalues[i]); + } + } + + results->voltageBattery = atoi(tbattery); + results->frequency = atoi(frequency); +} + +void sms_parse_information(uint8_t *rawvalues, SmsData *results) { + /* Count from 1 to ignore first char and remove 2 from BUFFER_SIZE + * to compensate the start and ignore '\r' from end. */ + memset(results->model, 0, sizeof(results->model)); + memset(results->version, 0, sizeof(results->version)); + + for (int i = 1; i < BUFFER_SIZE - 2; i++) { + if (i <= 12) { + snprintfcat(results->model, 24, "%c", rawvalues[i]); + } else { + snprintfcat(results->version, 6, "%c", rawvalues[i]); + } + } +} + +void sms_parse_results(uint8_t *rawvalues, SmsData *results) { + char buf[BUFFER_SIZE]; + uint8_t byte, mask; + long v; + double h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[1], (unsigned char)rawvalues[2]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->lastinputVac = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[3], (unsigned char)rawvalues[4]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->inputVac = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[5], (unsigned char)rawvalues[6]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->outputVac = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[7], (unsigned char)rawvalues[8]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->outputpower = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[9], (unsigned char)rawvalues[10]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->outputHz = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[11], (unsigned char)rawvalues[12]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->batterylevel = h; + + memset(buf, 0, BUFFER_SIZE); + sprintf(buf, "0x%02x%02x", (unsigned char)rawvalues[13], (unsigned char)rawvalues[14]); + v = strtol(buf, NULL, 16); /* 16 == hex */ + h = v / 10; + results->temperatureC = h; + + byte = rawvalues[15]; + mask = 1; + + results->beepon = ((byte & (mask << 0)) != 0) ? true : false; + results->shutdown = ((byte & (mask << 1)) != 0) ? true : false; + results->test = ((byte & (mask << 2)) != 0) ? true : false; + results->upsok = ((byte & (mask << 3)) != 0) ? true : false; + results->boost = ((byte & (mask << 4)) != 0) ? true : false; + results->bypass = ((byte & (mask << 5)) != 0) ? true : false; + results->lowbattery = ((byte & (mask << 6)) != 0) ? true : false; + results->onbattery = ((byte & (mask << 7)) != 0) ? true : false; +} + +static int get_ups_nominal() { + uint8_t length; + ssize_t ret; + + upsdebugx(LOG_DEBUG, "get_ups_nominal"); + + length = sms_prepare_get_status(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(LOG_ERR, "Communication error while writing to port"); + return -1; + } + memset(bufIn, 0, BUFFER_SIZE); + ret = ser_get_buf_len(upsfd, &bufIn[0], BUFFER_SIZE, 3, 1000); + + if (ret < RESULT_SIZE) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return -1; + } + + upsdebugx(3, "Get nominal Ok: received byte %lu", ret); + + if (bufIn[0] == '=' || bufIn[0] == '<' || bufIn[0] == '>') { + sms_parse_results(&bufIn[0], &DeviceData); + return 0; + } + + upsdebugx(3, "Invalid query response from 'Q' command"); + return -1; +} + +static int get_ups_information() { + uint8_t length; + ssize_t ret; + + upsdebugx(LOG_DEBUG, "get_ups_information"); + + length = sms_prepare_get_information(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(LOG_ERR, "Communication error while writing to port"); + return -1; + } + memset(bufIn, 0, BUFFER_SIZE); + ret = ser_get_buf_len(upsfd, &bufIn[0], BUFFER_SIZE, 3, 1000); + + if (ret < RESULT_SIZE) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return -1; + } + + upsdebugx(3, "Get information Ok: received byte %lu", ret); + + if (bufIn[0] == ';' || bufIn[0] == ':') { + sms_parse_information(&bufIn[0], &DeviceData); + return 0; + } + + upsdebugx(3, "Invalid query response from 'I' command"); + return -1; +} + +static int get_ups_features() { + uint8_t length; + ssize_t ret; + + upsdebugx(LOG_DEBUG, "get_ups_features"); + + length = sms_prepare_get_features(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(LOG_ERR, "Communication error while writing to port"); + return -1; + } + memset(bufIn, 0, BUFFER_SIZE); + ret = ser_get_buf_len(upsfd, &bufIn[0], BUFFER_SIZE, 3, 1000); + + if (ret < RESULT_SIZE) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return -1; + } + + upsdebugx(LOG_DEBUG, "Get features Ok: received byte %lu", ret); + + if (bufIn[0] == ';' || bufIn[0] == ':') { + sms_parse_features(&bufIn[0], &DeviceData); + return 0; + } + + upsdebugx(LOG_ERR, "Invalid query response from 'F' command"); + return -1; +} + +static int sms_instcmd(const char *cmdname, const char *extra) { + size_t length; + + if (!strcasecmp(cmdname, "test.battery.start")) { + long delay = extra ? strtol(extra, NULL, 10) : 10; + length = sms_prepare_test_battery_nsec(&bufOut[0], delay); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send test.battery.start"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command test.battery.start OK!"); + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "test.battery.start.quick")) { + length = sms_prepare_test_battery_low(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send test.battery.start.quick"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command test.battery.start.quick OK!"); + + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "test.battery.stop")) { + length = sms_prepare_cancel_test(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send test.battery.stop"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command test.battery.stop OK!"); + + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "beeper.toggle")) { + length = sms_prepare_set_beep(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send beeper.toggle"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command beeper.toggle OK!"); + + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "shutdown.return")) { + length = sms_prepare_shutdown_restore(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send shutdown.return"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command shutdown.return OK!"); + + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "shutdown.reboot")) { + long delay = extra ? strtol(extra, NULL, bootdelay) : bootdelay; + length = sms_prepare_shutdown_nsec(&bufOut[0], delay); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send shutdown.reboot"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command shutdown.reboot OK!"); + + return STAT_INSTCMD_HANDLED; + } + + if (!strcasecmp(cmdname, "shutdown.stop")) { + length = sms_prepare_cancel_shutdown(&bufOut[0]); + + if (ser_send_buf(upsfd, bufOut, length) == 0) { + upsdebugx(3, "failed to send shutdown.stop"); + return STAT_INSTCMD_FAILED; + } + upsdebugx(3, "command shutdown.stop OK!"); + + return STAT_INSTCMD_HANDLED; + } + + upslogx(LOG_NOTICE, "sms_instcmd: unknown command [%s]", cmdname); + return STAT_INSTCMD_UNKNOWN; +} + +static int sms_setvar(const char *varname, const char *val) { + if (!strcasecmp(varname, "ups.delay.reboot")) { + int ipv = atoi(val); + if (ipv >= 0) + bootdelay = (unsigned int)ipv; + dstate_setinfo("ups.delay.reboot", "%u", bootdelay); + return STAT_SET_HANDLED; + } + return STAT_SET_UNKNOWN; +} + +void upsdrv_initinfo(void) { + char *battery_status; + + upsdebugx(LOG_DEBUG, "upsdrv_initinfo"); + + if (get_ups_features() != 0) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return; + } + if (get_ups_information() != 0) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return; + } + + if (get_ups_nominal() == 0) { + dstate_setinfo("device.model", "%s", DeviceData.model); + dstate_setinfo("ups.firmware", "%s", DeviceData.version); + dstate_setinfo("input.voltage.nominal", "%s", DeviceData.voltageRange); + dstate_setinfo("input.current.nominal", "%s", DeviceData.currentRange); + dstate_setinfo("output.frequency.nominal", "%d", DeviceData.frequency); + dstate_setinfo("ups.beeper.status", "%s", (DeviceData.beepon == 1) ? "enabled" : "disabled"); + + dstate_setinfo("input.voltage.extended", "%.2f", DeviceData.lastinputVac); + + dstate_setinfo("input.voltage", "%.2f", DeviceData.inputVac); + dstate_setinfo("output.voltage", "%.2f", DeviceData.outputVac); + dstate_setinfo("ups.load", "%.2f", DeviceData.outputpower); + dstate_setinfo("output.frequency", "%.2f", DeviceData.outputHz); + dstate_setinfo("battery.charge", "%.2f", DeviceData.batterylevel); + + dstate_setinfo("battery.voltage.nominal", "%d", DeviceData.voltageBattery); + dstate_setinfo("battery.packs", "%d", DeviceData.voltageBattery / 12); + dstate_setinfo("battery.voltage", "%.2f", (DeviceData.voltageBattery * DeviceData.batterylevel) / 100); + dstate_setinfo("ups.temperature", "%.2f", DeviceData.temperatureC); + + if (DeviceData.onbattery && (uint8_t)DeviceData.batterylevel < 100) { + upsdebugx(LOG_DEBUG, "on battery and battery < last battery"); + battery_status = "discharging"; + } else if (!DeviceData.onbattery && (uint8_t)DeviceData.batterylevel < 100) { + upsdebugx(LOG_DEBUG, "on power and battery > last battery"); + battery_status = "charging"; + } else if (!DeviceData.onbattery && (uint8_t)DeviceData.batterylevel == 100) { + upsdebugx(LOG_DEBUG, "on power and battery == 100"); + battery_status = "resting"; + } else { + upsdebugx(LOG_DEBUG, "none, floating"); + battery_status = "floating"; + } + dstate_setinfo("battery.charger.status", "%s", battery_status); + } else { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return; + } + + dstate_addcmd("test.battery.start"); + dstate_addcmd("test.battery.start.quick"); + dstate_addcmd("test.battery.stop"); + dstate_addcmd("beeper.toggle"); + dstate_addcmd("shutdown.return"); + dstate_addcmd("shutdown.stop"); + dstate_addcmd("shutdown.reboot"); + + upsh.instcmd = sms_instcmd; + upsh.setvar = sms_setvar; +} + +void upsdrv_updateinfo(void) { + char *battery_status; + + upsdebugx(LOG_DEBUG, "upsdrv_updateinfo"); + + if (get_ups_nominal() != 0) { + upslogx(LOG_ERR, "Short read from UPS"); + dstate_datastale(); + return; + } + dstate_setinfo("device.model", "%s", DeviceData.model); + dstate_setinfo("ups.firmware", "%s", DeviceData.version); + dstate_setinfo("battery.voltage.nominal", "%s", DeviceData.voltageRange); + dstate_setinfo("output.frequency.nominal", "%d", DeviceData.frequency); + dstate_setinfo("ups.beeper.status", "%s", (DeviceData.beepon == 1) ? "enabled" : "disabled"); + + dstate_setinfo("input.voltage.extended", "%.2f", DeviceData.lastinputVac); + + dstate_setinfo("input.voltage", "%.2f", DeviceData.inputVac); + dstate_setinfo("output.voltage", "%.2f", DeviceData.outputVac); + dstate_setinfo("ups.load", "%.2f", DeviceData.outputpower); + dstate_setinfo("output.frequency", "%.2f", DeviceData.outputHz); + dstate_setinfo("battery.charge", "%.2f", DeviceData.batterylevel); + + dstate_setinfo("battery.voltage.nominal", "%d", DeviceData.voltageBattery); + dstate_setinfo("battery.packs", "%d", DeviceData.voltageBattery / 12); + dstate_setinfo("battery.voltage", "%.2f", (DeviceData.voltageBattery * DeviceData.batterylevel) / 100); + dstate_setinfo("ups.temperature", "%.2f", DeviceData.temperatureC); + + upsdebugx(LOG_DEBUG, "battery level: %.2f", DeviceData.batterylevel); + upsdebugx(LOG_DEBUG, "bypass: %d", DeviceData.bypass); + upsdebugx(LOG_DEBUG, "onBattery: %d", DeviceData.onbattery); + + if (DeviceData.onbattery && (uint8_t)DeviceData.batterylevel < 100) { + upsdebugx(LOG_DEBUG, "on battery and battery < last battery"); + battery_status = "discharging"; + } else if (!DeviceData.onbattery && (uint8_t)DeviceData.batterylevel < 100) { + upsdebugx(LOG_DEBUG, "on power and battery > last battery"); + battery_status = "charging"; + } else if (!DeviceData.onbattery && (uint8_t)DeviceData.batterylevel == 100) { + upsdebugx(LOG_DEBUG, "on power and battery == 100"); + battery_status = "resting"; + } else { + upsdebugx(LOG_DEBUG, "none, floating"); + battery_status = "floating"; + } + dstate_setinfo("battery.charger.status", "%s", battery_status); + + status_init(); + + if (DeviceData.bypass) { + upsdebugx(LOG_DEBUG, "setting status to BYPASS"); + status_set("BYPASS"); + } else if (DeviceData.onbattery) { + upsdebugx(LOG_DEBUG, "setting status to OB"); + status_set("OB"); + } else if (DeviceData.lowbattery) { + upsdebugx(LOG_DEBUG, "setting status to LB"); + status_set("LB"); + } else if (!DeviceData.upsok) { + upsdebugx(LOG_DEBUG, "setting status to RB"); + status_set("RB"); + } else if (DeviceData.boost) { + upsdebugx(LOG_DEBUG, "setting status to BOOST"); + status_set("BOOST"); + } else if (!DeviceData.onbattery) { + /* sometimes the flag "onacpower" is not set */ + upsdebugx(LOG_DEBUG, "setting status to OL"); + status_set("OL"); + } else { + /* None of these parameters is ON, but we got some response, + * so the device is (administratively) OFF ? */ + upsdebugx(LOG_DEBUG, "setting status to OFF"); + status_set("OFF"); + } + + status_commit(); + dstate_dataok(); + + poll_interval = 5; +} + +void upsdrv_shutdown(void) { + /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ + int retry; + + /* maybe try to detect the UPS here, but try a shutdown even if + * 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 */ + + /* OL: this must power cycle the load if possible */ + + /* OB: the load must remain off until the power returns */ + upsdebugx(2, "upsdrv Shutdown execute"); + + for (retry = 1; retry <= MAXTRIES; retry++) { + if (sms_instcmd("shutdown.stop", NULL) != STAT_INSTCMD_HANDLED) { + continue; + } + + if (sms_instcmd("shutdown.return", NULL) != STAT_INSTCMD_HANDLED) { + continue; + } + + upslogx(LOG_ERR, "Shutting down"); + set_exit_flag(-2); /* EXIT_SUCCESS */ + return; + } + + upslogx(LOG_ERR, "Shutdown failed!"); + set_exit_flag(-1); +} + +void upsdrv_help(void) { +} + +/* list flags and values that you want to receive via -x */ +void upsdrv_makevartable(void) { + char msg[256]; + + upsdebugx(LOG_DEBUG, "upsdrv_makevartable"); + + snprintf(msg, sizeof msg, "Set reboot delay, in seconds (default=%d).", + DEFAULT_BOOTDELAY); + addvar(VAR_VALUE, "rebootdelay", msg); +} + +void upsdrv_initups(void) { + char *val; + + upsdebugx(LOG_DEBUG, "upsdrv_initups"); + + upsfd = ser_open(device_path); + ser_set_speed(upsfd, device_path, B2400); + + if ((val = getval("rebootdelay"))) { + int ipv = atoi(val); + if (ipv >= 0) + bootdelay = (unsigned int)ipv; + } +} + +void upsdrv_cleanup(void) { + upsdebugx(LOG_DEBUG, "upsdrv_cleanup"); + /* free(dynamic_mem); */ + ser_close(upsfd, device_path); +} + +uint8_t sms_prepare_get_status(uint8_t *buffer) { + buffer[0] = 'Q'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_get_information(uint8_t *buffer) { + buffer[0] = 'I'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_get_features(uint8_t *buffer) { + buffer[0] = 'F'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_set_beep(uint8_t *buffer) { + buffer[0] = 'M'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_test_battery_low(uint8_t *buffer) { + buffer[0] = 'L'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_test_battery_nsec(uint8_t *buffer, uint16_t delay) { + buffer[0] = 'T'; + buffer[1] = (uint8_t)(delay % 256); + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_shutdown_nsec(uint8_t *buffer, uint16_t delay) { + buffer[0] = 'S'; + buffer[1] = (uint8_t)(delay % 256); + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_shutdown_restore(uint8_t *buffer) { + buffer[0] = 'R'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_cancel_test(uint8_t *buffer) { + buffer[0] = 'D'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} + +uint8_t sms_prepare_cancel_shutdown(uint8_t *buffer) { + buffer[0] = 'C'; + buffer[1] = 255; + buffer[2] = 255; + buffer[3] = 255; + buffer[4] = 255; + buffer[5] = (buffer[0] + buffer[1] + buffer[2] + buffer[3] + buffer[4]) * 255; + buffer[6] = ENDCHAR; + + return 7; +} diff --git a/drivers/sms_ser.h b/drivers/sms_ser.h new file mode 100644 index 0000000000..a47c863f27 --- /dev/null +++ b/drivers/sms_ser.h @@ -0,0 +1,73 @@ +/* + * sms_ser.h: defines/macros protocol for SMS Brazil UPSes + * + * Copyright (C) 2023 - Alex W. Baule + * + * 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 + * + * Reference of the derivative work: riello driver + */ + +#ifndef NUT_SMS_SER_H_SEEN +#define NUT_SMS_SER_H_SEEN 1 + +#include /* bool type */ + +#include "nut_stdint.h" + +#define DEFAULT_BOOTDELAY 64 /* seconds (max 0xFF) */ +#define MAXTRIES 3 + +typedef struct { + char model[25]; /* device.model */ + char version[7]; /* ups.firmware */ + char voltageRange[15]; /* garbage from sms (it's a string with some strange items) */ + char currentRange[7]; /* garbage from sms (it's 000) maybe with some cleanup on string input.voltage.nominal */ + uint8_t voltageBattery; /* battery.voltage.nominal (DeviceData.voltageBattery / 12 = battery.packs) */ + uint8_t frequency; /* output.frequency.nominal */ + + bool beepon; /* ups.beeper.status */ + bool shutdown; /* ups.status = FSD (the shutdown has started by another via) */ + bool test; /* the UPS is testing the battery, need a status ? */ + bool upsok; /* ups.status or battery.status ? (Maybe RB if is False ?) */ + bool boost; /* ups.status = BOOST */ + bool bypass; /* ups.status = BYPASS */ + bool lowbattery; /* ups.status = LB (OL + LB or OB + LB ?) */ + bool onbattery; /* ups.status = OB + battery.charger.status = discharging */ + + float lastinputVac; /* garbage ? always 000 */ + float inputVac; /* input.voltage */ + float outputVac; /* output.voltage */ + float outputpower; /* ups.load */ + float outputHz; /* output.frequency */ + float batterylevel; /* battery.charge (batterylevel < 100 ? battery.charger.status = charging if onacpower/discharging if onbattery : resting) + * battery.voltage = (voltageBattery * batterylevel) / 100) + */ + float temperatureC; /* ups.temperature */ +} SmsData; + +void sms_parse_results(uint8_t* rawvalues, SmsData* results); +uint8_t sms_prepare_get_status(uint8_t* buffer); +uint8_t sms_prepare_get_information(uint8_t* buffer); +uint8_t sms_prepare_get_features(uint8_t* buffer); +uint8_t sms_prepare_set_beep(uint8_t* buffer); +uint8_t sms_prepare_test_battery_low(uint8_t* buffer); +uint8_t sms_prepare_test_battery_nsec(uint8_t* buffer, uint16_t delay); +uint8_t sms_prepare_shutdown_nsec(uint8_t* buffer, uint16_t delay); +uint8_t sms_prepare_shutdown_restore(uint8_t* buffer); +uint8_t sms_prepare_cancel_test(uint8_t* buffer); +uint8_t sms_prepare_cancel_shutdown(uint8_t* buffer); + +#endif /* NUT_SMS_SER_H_SEEN */ From 8e496b33e8c2a609ed4eb046f1d8b83a7b7b1760 Mon Sep 17 00:00:00 2001 From: moonbuggy <3319867+moonbuggy@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:56:41 +1100 Subject: [PATCH 1135/1232] use short instead of long/float Signed-off-by: moonbuggy <3319867+moonbuggy@users.noreply.github.com> --- drivers/optiups.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/optiups.c b/drivers/optiups.c index 4814b48af9..62cfa98aa4 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -488,22 +488,22 @@ void upsdrv_updateinfo(void) optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) ); r = optiquery( "NV" ); - float inV = strtol ( _buf, NULL, 10); + short inV = atoi ( _buf ); r = optiquery( "OV" ); - float outV = strtol ( _buf, NULL, 10); + short outV = atoi ( _buf ); r = optiquery( "FV" ); if ( r >= 1 ) { - float f = strtol ( _buf, NULL, 10 ); + short f = atoi ( _buf ); if ( f > 180 ) { inV = inV * 2; outV = outV * 2; } } - dstate_setinfo( "input.voltage", "%.1f", inV ); - dstate_setinfo( "output.voltage", "%.1f", outV ); + dstate_setinfo( "input.voltage", "%d", inV ); + dstate_setinfo( "output.voltage", "%d", outV ); } else optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) ); From 37e01e01d92dc60f6427091d90d1c66d58d4118b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 13:15:54 +0200 Subject: [PATCH 1136/1232] Jenkinsfile-dynamatrix: default a MAKE=make envvar if somehow missing (strange bug for autotools build scenarios) Signed-off-by: Jim Klimov --- Jenkinsfile-dynamatrix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index c44e565c52..ecc13835f7 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -55,7 +55,7 @@ import org.nut.dynamatrix.*; dynacfgPipeline.disableSlowBuildCIBuild_QEMU = false } - dynacfgPipeline.traceBuildShell_configureEnvvars = false// true + dynacfgPipeline.traceBuildShell_configureEnvvars = false// true dynacfgPipeline.traceBuildShell = false //true dynacfgPipeline.failFast = //true // @@ -98,7 +98,7 @@ import org.nut.dynamatrix.*; //'stageNameFunc': null, //'dynamatrixAxesLabels': [~/^OS_.+/, 'MAKE'], 'dynamatrixAxesLabels': ['OS_FAMILY', 'OS_DISTRO', 'MAKE'], - 'single': '( \${MAKE} shellcheck )', + 'single': '( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; \${MAKE} shellcheck )', 'multi': '(cd tests && SERVICE_FRAMEWORK="selftest" SHELL_PROGS="$SHELL_PROGS" ./nut-driver-enumerator-test.sh )', 'multiLabel': 'SHELL_PROGS', 'skipShells': [ 'zsh', 'tcsh', 'csh' ] @@ -233,7 +233,10 @@ import org.nut.dynamatrix.*; if (!dynacfgPipeline.containsKey('buildPhases')) { dynacfgPipeline.buildPhases = [:] } - dynacfgPipeline.buildPhases['distcheck'] = """( eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" + + // Imported from jenkins-dynamatrix JSL vars/autotools.groovy: + // a workaround for the cases of curiously missing MAKE envvar... + dynacfgPipeline.buildPhases['distcheck'] = """( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" // Note: shellcheck/spellcheck/... require autotools currently // or need to be redefined with respective BUILD_TYPE From c61bfc3934de845e15ed1f49b9ba95afa371a14e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Oct 2023 13:15:54 +0200 Subject: [PATCH 1137/1232] Jenkinsfile-dynamatrix: default a MAKE=make envvar if somehow missing (strange bug for autotools build scenarios) Signed-off-by: Jim Klimov --- Jenkinsfile-dynamatrix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index ecc13835f7..0d08fa9c98 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -234,9 +234,9 @@ import org.nut.dynamatrix.*; dynacfgPipeline.buildPhases = [:] } - // Imported from jenkins-dynamatrix JSL vars/autotools.groovy: - // a workaround for the cases of curiously missing MAKE envvar... - dynacfgPipeline.buildPhases['distcheck'] = """( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" + // Imported from jenkins-dynamatrix JSL vars/autotools.groovy: + // a workaround for the cases of curiously missing MAKE envvar... + dynacfgPipeline.buildPhases['distcheck'] = """( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" // Note: shellcheck/spellcheck/... require autotools currently // or need to be redefined with respective BUILD_TYPE From 6f5b491d69b6237c33f3f55e728180149f5e7409 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 11:22:37 +0200 Subject: [PATCH 1138/1232] tests/generic_gpio_utest.c: fix warnings about formatting strings Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 55 ++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 542438b021..2f8c0dccf1 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -24,6 +24,7 @@ #include "main.h" #include "dstate.h" #include "attribute.h" +#include "nut_stdint.h" #include "generic_gpio_utest.h" #include @@ -177,22 +178,41 @@ int main(int argc, char **argv) { cases_failed=0; fEof = 1; for(unsigned int i=0; fEof!=EOF; i++) { + char fmt[16]; do { fEof=fscanf(testData, "%s", rules); } while(strcmp("*", rules)); fEof=fscanf(testData, "%s", testType); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + /* To avoid safety warnings, must provide a limit + * here (bufsize - 1), and use fixed format strings + * because scanf() does not support asterisk for + * width specifier; have to create it on the fly. + */ + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(rules)-1); fEof=fscanf(testData, "%s", rules); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif if(fEof!=EOF) { if(!strcmp(testType, "rules")) { struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); jmp_result = setjmp(env_buffer); if(jmp_result) { /* test case exiting */ generic_gpio_close(upsfdtest); - printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 1)], testType, i, rules); + printf("%s %s test rule %u [%s]\n", pass_fail[get_test_status(upsfdtest, 1)], testType, i, rules); } else { /* run test case */ get_ups_rules(upsfdtest, (unsigned char *)rules); generic_gpio_close(upsfdtest); - printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 0)], testType, i, rules); + printf("%s %s test rule %u [%s]\n", pass_fail[get_test_status(upsfdtest, 0)], testType, i, rules); } } if(!strcmp(testType, "states")) { @@ -208,10 +228,10 @@ int main(int argc, char **argv) { fEof=fscanf(testData, "%d", &expectedStateValue); calculatedStateValue=calc_rule_states(upsfdtest->upsLinesStates, upsfdtest->rules[j]->cRules, upsfdtest->rules[j]->subCount, 0); if(expectedStateValue==calculatedStateValue) { - printf("%s %s test rule %d [%s]\n", pass_fail[0], testType, i, rules); + printf("%s %s test rule %u [%s]\n", pass_fail[0], testType, i, rules); cases_passed++; } else { - printf("%s %s test rule %d [%s] %s", pass_fail[1], testType, i, rules, upsfdtest->rules[j]->stateName); + printf("%s %s test rule %u [%s] %s", pass_fail[1], testType, i, rules, upsfdtest->rules[j]->stateName); for(int k=0; kupsLinesCount; k++) { printf(" %d", upsfdtest->upsLinesStates[k]); } @@ -259,7 +279,7 @@ int main(int argc, char **argv) { if(!strcmp(chargeLow,".") && !strcmp(charge,".") && currCharge!=NULL) failed=1; generic_gpio_close(upsfdtest); } - printf("%s %s test rule %d [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", + printf("%s %s test rule %u [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", pass_fail[failed], testType, i, rules, upsStatus, chargeStatus, charge, chargeLow, currUpsStatus, currChargerStatus, currCharge); @@ -275,8 +295,27 @@ int main(int argc, char **argv) { int expecting_failure, failed; char subType[NUT_GPIO_SUBTYPEBUF]; fEof=fscanf(testData, "%d", &expecting_failure); - fEof=fscanf(testData, "%s", chipNameLocal); - fEof=fscanf(testData, "%s", subType); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + /* To avoid safety warnings, must provide a limit + * here (bufsize - 1), and use fixed format strings + * because scanf() does not support asterisk for + * width specifier; have to create it on the fly. + */ + snprintf(fmt, sizeof(fmt), "%%%us", NUT_GPIO_CHIPNAMEBUF-1); + fEof=fscanf(testData, fmt, chipNameLocal); + snprintf(fmt, sizeof(fmt), "%%%us", NUT_GPIO_SUBTYPEBUF-1); + fEof=fscanf(testData, fmt, subType); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif jmp_result = setjmp(env_buffer); failed = expecting_failure; if(jmp_result) { /* test case exiting */ @@ -315,7 +354,7 @@ int main(int argc, char **argv) { } upsdrv_cleanup(); } - printf("%s %s %s test rule %d [%s] %s %d\n", + printf("%s %s %s test rule %u [%s] %s %d\n", pass_fail[failed], testType, subType, i, rules, chipNameLocal, expecting_failure); if(!failed) { cases_passed++; From 436ef40985489722dbe01cd8f8a28d44797616e5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:07:01 +0200 Subject: [PATCH 1139/1232] common/common.c: fix casting warnings Signed-off-by: Jim Klimov --- common/common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/common.c b/common/common.c index 89991619cb..c12587ae1d 100644 --- a/common/common.c +++ b/common/common.c @@ -687,7 +687,7 @@ double difftimeval(struct timeval x, struct timeval y) result.tv_sec = x.tv_sec - y.tv_sec; result.tv_usec = x.tv_usec - y.tv_usec; - d = 0.000001 * result.tv_usec + result.tv_sec; + d = 0.000001 * (double)(result.tv_usec) + (double)(result.tv_sec); return d; } @@ -718,7 +718,7 @@ static usec_t timespec_load(const struct timespec *ts) { if (ts->tv_sec < 0 || ts->tv_nsec < 0) return USEC_INFINITY; - if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) + if ((usec_t) ts->tv_sec > (UINT64_MAX - ((uint64_t)(ts->tv_nsec) / NSEC_PER_USEC)) / USEC_PER_SEC) return USEC_INFINITY; return @@ -767,7 +767,7 @@ double difftimespec(struct timespec x, struct timespec y) result.tv_sec = x.tv_sec - y.tv_sec; result.tv_nsec = x.tv_nsec - y.tv_nsec; - d = 0.000000001 * result.tv_nsec + result.tv_sec; + d = 0.000000001 * (double)(result.tv_nsec) + (double)(result.tv_sec); return d; } #endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ @@ -1265,7 +1265,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) if (((uintmax_t)ret) > (SIZE_MAX - LARGEBUF)) { goto vupslog_too_long; } - newbufsize = ret + LARGEBUF; + newbufsize = (size_t)ret + LARGEBUF; } /* else: errno, e.g. ERANGE printing: * "...(34 => Result too large)" */ if (nut_debug_level > 0) { From 0d54fb7a38bd85a7eaf8d3b92f73c5c1eb118aec Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:44:26 +0200 Subject: [PATCH 1140/1232] clients/upssched.c: fix casting warnings Signed-off-by: Jim Klimov --- clients/upssched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/upssched.c b/clients/upssched.c index 4b8e9c4ba9..029736bf07 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -959,7 +959,7 @@ static void start_daemon(TYPE_FD lockfd) if (d > 0 && d < 0.2) { d = (1.0 - d) * 1000000.0; upsdebugx(5, "Enforcing a throttling sleep: %f usec", d); - usleep(d); + usleep((useconds_t)d); } } } From 19245e5992cb6c7c226ca8d43bbb125fec4f2cf3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:44:51 +0200 Subject: [PATCH 1141/1232] drivers/dummy-ups.c: fix casting warnings Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 8a58242bce..3b4be2436c 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -130,7 +130,7 @@ void upsdrv_initinfo(void) /* Set max length for strings, if needed */ if (item->info_flags & ST_FLAG_STRING) - dstate_setaux(item->info_type, item->info_len); + dstate_setaux(item->info_type, (long)item->info_len); } } @@ -578,7 +578,7 @@ static int setvar(const char *varname, const char *val) /* Set max length for strings, if needed */ if (item->info_flags & ST_FLAG_STRING) - dstate_setaux(item->info_type, item->info_len); + dstate_setaux(item->info_type, (long)item->info_len); } else { From 2a05d516b8bda6d09608e4264e49e24cd4f8715d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:45:50 +0200 Subject: [PATCH 1142/1232] drivers/main.c: fix portability of chown() used as chgrp() Initial implementation passed -1 as uid to have it not changed. Not all OSes support that behavior. Signed-off-by: Jim Klimov --- drivers/main.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index c48e291ef7..b75ebaf83d 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -2276,19 +2276,27 @@ int main(int argc, char **argv) } else { struct stat statbuf; mode_t mode; - if (chown(sockname, -1, grp->gr_gid)) { - upsdebugx(1, "WARNING: chown failed: %s", + + if (stat(sockname, &statbuf)) { + upsdebugx(1, "WARNING: stat for chown failed: %s", strerror(errno) ); allOk = 0; + } else { + /* Here we do a portable chgrp() essentially: */ + if (chown(sockname, statbuf.st_uid, grp->gr_gid)) { + upsdebugx(1, "WARNING: chown failed: %s", + strerror(errno) + ); + allOk = 0; + } } + /* Refresh file info */ if (stat(sockname, &statbuf)) { /* Logically we'd fail chown above if file - * does not exist or is not accessible, but - * practically we only need stat for chmod - */ - upsdebugx(1, "WARNING: stat failed: %s", + * does not exist or is not accessible */ + upsdebugx(1, "WARNING: stat for chmod failed: %s", strerror(errno) ); allOk = 0; From 2b640e37f805c719ecc307a8e6ac25a2689ae39c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:47:08 +0200 Subject: [PATCH 1143/1232] drivers/main.c: fix indentation Signed-off-by: Jim Klimov --- drivers/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index b75ebaf83d..64112635d7 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1945,10 +1945,10 @@ int main(int argc, char **argv) upslogx(LOG_INFO, "Request to killpower via running driver returned code %d", cmdret); if (cmdret == 0) /* Note: many drivers would abort with - * "shutdown not supported" at this - * point... we would too, but later - * and at a higher time/processing cost. - */ + * "shutdown not supported" at this + * point... we would too, but later + * and at a higher time/processing cost. + */ exit (EXIT_SUCCESS); /* else fall through to legacy handling */ } From 2bcb7031ab58675103fd389fa6784cb3340f8f8d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:49:55 +0200 Subject: [PATCH 1144/1232] drivers/main.c: fix cmdret=upsdrvquery_oneshot() as a generally ssize_t value Signed-off-by: Jim Klimov --- drivers/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 64112635d7..cefb6cdd5c 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1920,7 +1920,7 @@ int main(int argc, char **argv) * approach (kill sibling if needed, recapture device, * command it...) */ - int cmdret = -1; + ssize_t cmdret = -1; struct timeval tv; /* Post the query and wait for reply */ @@ -1942,7 +1942,7 @@ int main(int argc, char **argv) if (cmdret < 0) { upsdebugx(1, "Socket dialog with the other driver instance: %s", strerror(errno)); } else { - upslogx(LOG_INFO, "Request to killpower via running driver returned code %d", cmdret); + upslogx(LOG_INFO, "Request to killpower via running driver returned code %" PRIiSIZE, cmdret); if (cmdret == 0) /* Note: many drivers would abort with * "shutdown not supported" at this @@ -1966,7 +1966,7 @@ int main(int argc, char **argv) if (cmd && !strcmp(cmd, SIGCMD_RELOAD_OR_ERROR)) #endif /* WIN32 */ { /* Not a signal, but a socket protocol action */ - int cmdret = -1; + ssize_t cmdret = -1; char buf[LARGEBUF]; struct timeval tv; @@ -1982,11 +1982,11 @@ int main(int argc, char **argv) upslog_with_errno(LOG_ERR, "Socket dialog with the other driver instance"); } else { /* TODO: handle buf reply contents */ - upslogx(LOG_INFO, "Request to reload-or-error returned code %d", cmdret); + upslogx(LOG_INFO, "Request to reload-or-error returned code %" PRIiSIZE, cmdret); } /* exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); */ - exit((cmdret < 0) ? 255 : cmdret); + exit(((cmdret < 0) || (((uintmax_t)cmdret) > ((uintmax_t)INT_MAX))) ? 255 : (int)cmdret); } #ifndef WIN32 From 16a5c27dcc05072926fa0d10d4cd977b3f148b79 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:53:18 +0200 Subject: [PATCH 1145/1232] drivers/upsdrvquery.c: fix casting warnings Signed-off-by: Jim Klimov --- drivers/upsdrvquery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 3f273e5d19..05f54564ce 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -324,7 +324,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { size_t buflen = strlen(buf); #ifndef WIN32 - int ret; + ssize_t ret; #else DWORD bytesWritten = 0; BOOL result = FALSE; @@ -384,7 +384,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { char *buf; upsdrvquery_read_timeout(conn, tv); gettimeofday(&now, NULL); - if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { + if (difftimeval(now, start) > ((double)(tv.tv_sec) + 0.000001 * (double)(tv.tv_usec))) { upsdebugx(5, "%s: requested timeout expired", __func__); break; } @@ -414,7 +414,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } /* Diminishing timeouts for read() */ - tv.tv_usec -= difftimeval(now, start); + tv.tv_usec -= (suseconds_t)(difftimeval(now, start)); while (tv.tv_usec < 0) { tv.tv_sec--; tv.tv_usec = 1000000 + tv.tv_usec; // Note it is negative @@ -563,7 +563,7 @@ ssize_t upsdrvquery_request( continue; } - if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { + if (difftimeval(now, start) > ((double)(tv.tv_sec) + 0.000001 * (double)(tv.tv_usec))) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); return -1; From 858f5ff455cb5c3fb46a88731d4b1a50e0be19bf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 14:55:38 +0200 Subject: [PATCH 1146/1232] drivers/clone.c: fix casting warnings Signed-off-by: Jim Klimov --- drivers/clone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clone.c b/drivers/clone.c index c12cc55d4b..9f963b09a6 100644 --- a/drivers/clone.c +++ b/drivers/clone.c @@ -570,7 +570,7 @@ void upsdrv_updateinfo(void) if (ups.timer.shutdown >= 0) { - ups.timer.shutdown -= difftime(now, last_poll); + ups.timer.shutdown -= (suseconds_t)(difftime(now, last_poll)); if (ups.timer.shutdown < 0) { const char *val; @@ -589,7 +589,7 @@ void upsdrv_updateinfo(void) } else if (ups.timer.start >= 0) { if (online) { - ups.timer.start -= difftime(now, last_poll); + ups.timer.start -= (suseconds_t)(difftime(now, last_poll)); } else { ups.timer.start = ondelay; } From e502c2e73b541c5a8fe5fda4144268067b033b02 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 23:20:03 +0200 Subject: [PATCH 1147/1232] Add a fallback inet_ntop() implementation Needed for tools/nut-scanner/scan_xml_http.c on MinGW cross-builds Signed-off-by: Jim Klimov --- common/wincompat.c | 190 +++++++++++++++++++++++++++++- configure.ac | 51 +++++++- include/wincompat.h | 4 + tools/nut-scanner/scan_xml_http.c | 3 + 4 files changed, 244 insertions(+), 4 deletions(-) diff --git a/common/wincompat.c b/common/wincompat.c index 4d3467e3d5..745b0bf9e3 100644 --- a/common/wincompat.c +++ b/common/wincompat.c @@ -22,6 +22,17 @@ #include "wincompat.h" #include "nut_stdint.h" +#if ! HAVE_INET_PTON +# include +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#endif + #if (0) extern int errno; #endif @@ -204,6 +215,181 @@ const char* inet_ntop(int af, const void* src, char* dst, size_t cnt) } #endif /* HAVE_INET_NTOP */ +#if ! HAVE_INET_PTON +/* Fallback implementation of inet_pton() for systems that lack it, + * such as older versions of Windows (including MinGW builds that do + * not specifically target _WIN32_WINNT or newer). + * + * Based on code attributed to Paul Vixie, 1996, + * sourced from https://stackoverflow.com/a/15370175/4715872 + */ + +#define NS_INADDRSZ sizeof(struct in_addr) /* 4 */ +#define NS_IN6ADDRSZ sizeof(struct in6_addr) /* 16 */ +#define NS_INT16SZ sizeof(uint16_t) /* 2 */ + +static int inet_pton4(const char *src, void *dst) +{ + uint8_t tmp[NS_INADDRSZ], *tp; /* for struct in_addr *dst */ + + int saw_digit = 0; + int octets = 0; + int ch; + + *(tp = tmp) = 0; + + while ((ch = *src++) != '\0') + { + if (ch >= '0' && ch <= '9') + { + uint32_t n = *tp * 10 + (ch - '0'); + + if (saw_digit && *tp == 0) + return 0; + + if (n > 255) + return 0; + + *tp = n; + if (!saw_digit) + { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } + else if (ch == '.' && saw_digit) + { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } + else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, NS_INADDRSZ); + + return 1; +} + +static int inet_pton6(const char *src, void *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + uint8_t tmp[NS_IN6ADDRSZ]; /* for struct in6_addr *dst */ + + uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); + uint8_t *endp = tp + NS_IN6ADDRSZ; + uint8_t *colonp = NULL; + + const char *curtok = NULL; + int saw_xdigit = 0; + uint32_t val = 0; + int ch; + + /* Leading :: requires some special handling. */ + if (*src == ':') + { + if (*++src != ':') + return 0; + } + + curtok = src; + + while ((ch = tolower(*src++)) != '\0') + { + const char *pch = strchr(xdigits, ch); + if (pch != NULL) + { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + if (ch == ':') + { + curtok = src; + if (!saw_xdigit) + { + if (colonp) + return 0; + colonp = tp; + continue; + } + else if (*src == '\0') + { + return 0; + } + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, (char*) tp) > 0) + { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) + { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) + { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return 0; + + for (i = 1; i <= n; i++) + { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + return 1; +} + +int inet_pton(int af, const char *src, void *dst) +{ + switch (af) + { + case AF_INET: + return inet_pton4(src, dst); + case AF_INET6: + return inet_pton6(src, dst); + default: + return -1; + } +} +#endif /* ! HAVE_INET_PTON */ + /* "system" call seems to handle path with blank name incorrectly */ int win_system(const char * command) { @@ -1448,9 +1634,9 @@ speed_t cfgetospeed(const struct termios *t) return t->c_ospeed; } -#else +#else /* !WIN32 */ /* Just avoid: ISO C forbids an empty translation unit [-Werror=pedantic] */ int main (int argc, char ** argv); -#endif +#endif /* WIN32 */ diff --git a/configure.ac b/configure.ac index 313870565a..6d9976456b 100644 --- a/configure.ac +++ b/configure.ac @@ -1171,8 +1171,55 @@ AS_IF([test x"${ac_cv_func_inet_ntop}" = xyes], [AC_DEFINE([HAVE_INET_NTOP], 1, [defined if system has the inet_ntop() method])], [AC_MSG_WARN([Required C library routine inet_ntop() not found]) AS_CASE([${target_os}], - [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] - ) + [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] + ) + ] + ) + +AC_CACHE_CHECK([for inet_pton() with IPv4 and IPv6 support], + [ac_cv_func_inet_pton], + [AC_LANG_PUSH([C]) + dnl e.g. add "-lws2_32" for mingw builds + dnl the NETLIBS are set by NUT_CHECK_SOCKETLIB above + SAVED_LIBS="$LIBS" + LIBS="$LIBS $NETLIBS" + AX_RUN_OR_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#if HAVE_WINDOWS_H +# undef inline +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#else +# include +#endif +#include +]], + [[/* int inet_pton(int af, const char *src, char *dst); */ +struct in_addr ipv4; +struct in6_addr ipv6; +printf("%i", inet_pton(AF_INET, "1.2.3.4", &ipv4)); +printf("%i", inet_pton(AF_INET6, "::1", &ipv6)) +/* autoconf adds ";return 0;" */ +]])], + [ac_cv_func_inet_pton=yes], [ac_cv_func_inet_pton=no] + ) + AC_LANG_POP([C]) + LIBS="$SAVED_LIBS" +]) +AS_IF([test x"${ac_cv_func_inet_pton}" = xyes], + [AC_DEFINE([HAVE_INET_PTON], 1, [defined if system has the inet_pton() method])], + [AC_MSG_WARN([Required C library routine inet_pton() not found]) + AS_CASE([${target_os}], + [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] + ) ] ) diff --git a/include/wincompat.h b/include/wincompat.h index c2fa2f8c1c..d9b9cc8458 100644 --- a/include/wincompat.h +++ b/include/wincompat.h @@ -99,6 +99,10 @@ const char* inet_ntop(int af, const void* src, char* dst, size_t cnt); # endif #endif +#if ! HAVE_INET_PTON +int inet_pton(int af, const char *src, void *dst); +#endif + /* from the MSDN getaddrinfo documentation : */ #define EAI_AGAIN WSATRY_AGAIN #define EAI_BADFLAGS WSAEINVAL diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index b9ebcdb907..6348a9bad7 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -44,6 +44,9 @@ on Windows 2000 and older versions */ #include #include +# if ! HAVE_INET_PTON +# include "wincompat.h" /* fallback inet_ntop where needed */ +# endif #endif #include From 717a4f34b975e590d7a37b87bf9388e978a1790b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Oct 2023 23:50:55 +0200 Subject: [PATCH 1148/1232] drivers/apcupsd-ups.c: port bits of poll.h to have this buildable on older WIN32 Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index cf6443f385..772b618c95 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -31,7 +31,22 @@ # include /* nfds_t */ #else typedef unsigned long int nfds_t; -#endif + +# ifndef POLLRDNORM +# define POLLRDNORM 0x0100 +# endif +# ifndef POLLRDBAND +# define POLLRDBAND 0x0200 +# endif +# ifndef POLLIN +# define POLLIN (POLLRDNORM | POLLRDBAND) +# endif +typedef struct pollfd { + SOCKET fd; + short events; + short revents; +}; +#endif /* !HAVE_POLL_H */ #include "main.h" #include "apcupsd-ups.h" From a0ab7219c8adb26802e255cf9d47e581706d209d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 00:02:23 +0200 Subject: [PATCH 1149/1232] include/wincompat.h: comment correct portable arg type for inet_ntop() Signed-off-by: Jim Klimov --- include/wincompat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wincompat.h b/include/wincompat.h index d9b9cc8458..c5178d05c9 100644 --- a/include/wincompat.h +++ b/include/wincompat.h @@ -95,7 +95,7 @@ int sktclose(int fh); */ const char* inet_ntop(int af, const void* src, char* dst, int cnt); # else -const char* inet_ntop(int af, const void* src, char* dst, size_t cnt); +const char* inet_ntop(int af, const void* src, char* dst, size_t /* socklen_t */ cnt); # endif #endif From 5d1236b52cf2b2c72a4560803018f087b2029da4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 00:11:50 +0200 Subject: [PATCH 1150/1232] m4/ax_run_or_link_ifelse.m4: make more effort to detect undefined-ness of methods Signed-off-by: Jim Klimov --- m4/ax_run_or_link_ifelse.m4 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/m4/ax_run_or_link_ifelse.m4 b/m4/ax_run_or_link_ifelse.m4 index 0e36c7efa2..994994b015 100644 --- a/m4/ax_run_or_link_ifelse.m4 +++ b/m4/ax_run_or_link_ifelse.m4 @@ -12,10 +12,16 @@ dnl # [ACTION-IF-CROSS-COMPILING = RUNTIME-ERROR]) dnl # ------------------------------------------------------- AC_DEFUN([AX_RUN_OR_LINK_IFELSE], [ + myCFLAGS="$CFLAGS" + myCXXFLAGS="$CXXFLAGS" + CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration" + CXXFLAGS="$myCXXFLAGS -Werror -Werror=implicit-function-declaration" AC_RUN_IFELSE([$1], [$2], [$3], [ AC_MSG_WARN([Current build is a cross-build, so not running test binaries, just linking them]) AC_LINK_IFELSE([$1], [$2], [$3]) ] ) + CFLAGS="$myCFLAGS" + CXXFLAGS="$myCXXFLAGS" ]) From 6aed0ee139604e0c9a583974504043d4e66a22ee Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 00:19:44 +0200 Subject: [PATCH 1151/1232] configure.ac: detect availability of struct pollfd Signed-off-by: Jim Klimov --- configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/configure.ac b/configure.ac index 6d9976456b..66821dde42 100644 --- a/configure.ac +++ b/configure.ac @@ -1223,6 +1223,51 @@ AS_IF([test x"${ac_cv_func_inet_pton}" = xyes], ] ) +AC_CACHE_CHECK([for struct pollfd], + [ac_cv_struct_pollfd], + [AC_LANG_PUSH([C]) + dnl e.g. add "-lws2_32" for mingw builds + dnl the NETLIBS are set by NUT_CHECK_SOCKETLIB above + SAVED_LIBS="$LIBS" + LIBS="$LIBS $NETLIBS" + AX_RUN_OR_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#if HAVE_WINDOWS_H +# undef inline +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#else +# include +#endif +#include +]], + [[ +struct pollfd pfd; +pfd.fd = 0; +/* autoconf adds ";return 0;" */ +]])], + [ac_cv_struct_pollfd=yes], [ac_cv_struct_pollfd=no] + ) + AC_LANG_POP([C]) + LIBS="$SAVED_LIBS" +]) +AS_IF([test x"${ac_cv_struct_pollfd}" = xyes], + [AC_DEFINE([HAVE_STRUCT_POLLFD], 1, [defined if system has the struct pollfd type])], + [AC_MSG_WARN([Required C library type struct pollfd not found]) + AS_CASE([${target_os}], + [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] + ) + ] + ) + dnl ---------------------------------------------------------------------- dnl Check for python binary program names per language version dnl to embed into scripts and Make rules From 51388550374de04b68b26cdc0d9026e6892373be Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 00:20:11 +0200 Subject: [PATCH 1152/1232] drivers/apcupsd-ups.c: use detected availability of struct pollfd to define or not the fallback Signed-off-by: Jim Klimov --- drivers/apcupsd-ups.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 772b618c95..82bc3af631 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -41,11 +41,14 @@ typedef unsigned long int nfds_t; # ifndef POLLIN # define POLLIN (POLLRDNORM | POLLRDBAND) # endif +# if ! HAVE_STRUCT_POLLFD typedef struct pollfd { SOCKET fd; short events; short revents; -}; +} pollfd_t; +# define HAVE_STRUCT_POLLFD 1 +# endif #endif /* !HAVE_POLL_H */ #include "main.h" From dd06249ecb9d58e8c0d42d037f85f01465de6185 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 10:43:57 +0200 Subject: [PATCH 1153/1232] docs/man/Makefile.am: fix EXTRA_DIST of driver man page sources even if the build was configured for just some subset of drivers [#2081] Signed-off-by: Jim Klimov --- docs/man/Makefile.am | 112 ++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 9944c46560..2326ea1c1d 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -37,7 +37,7 @@ MAN_CONF_PAGES = \ upsd.users.5 \ upsmon.conf.5 \ upssched.conf.5 -endif +endif WITH_MANS man5_MANS = $(MAN_CONF_PAGES) @@ -81,7 +81,7 @@ MAN_CLIENT_PAGES = \ upsmon.8 \ upsrw.8 \ upssched.8 -endif +endif WITH_MANS man8_MANS = $(MAN_CLIENT_PAGES) @@ -102,7 +102,7 @@ SRC_TOOL_PAGES = nut-scanner.txt nut-recorder.txt if WITH_MANS MAN_TOOL_PAGES = nut-scanner.8 nut-recorder.8 -endif +endif WITH_MANS man8_MANS += $(MAN_TOOL_PAGES) @@ -127,12 +127,12 @@ MAN8_CGI_PAGES = \ upsset.cgi.8 \ upsstats.cgi.8 \ upsimage.cgi.8 -endif +endif WITH_MANS if WITH_CGI man5_MANS += $(MAN5_CGI_PAGES) man8_MANS += $(MAN8_CGI_PAGES) -endif +endif WITH_CGI HTML_CGI_MANS = \ hosts.conf.html \ @@ -318,7 +318,7 @@ MAN1_DEV_PAGES = \ MAN8_DEV_PAGES = \ sockdebug.8 -endif +endif WITH_MANS if WITH_DEV man3_MANS = $(MAN3_DEV_PAGES) @@ -326,9 +326,9 @@ man8_MANS += $(MAN8_DEV_PAGES) if !WITH_PKG_CONFIG man1_MANS = $(MAN1_DEV_PAGES) -endif -# WITH_DEV -endif +endif !WITH_PKG_CONFIG + +endif WITH_DEV HTML_DEV_MANS = \ upsclient.html \ @@ -382,11 +382,11 @@ HTML_DEV_MANS = \ # Drivers related manpages -# (--with-drivers=...) +# If (--with-drivers=...) then we only build specific documents, however +# still do track (and EXTRA_DIST, and spellcheck) all available sources. if SOME_DRIVERS man8_MANS += $(DRIVER_MAN_LIST) - -else +endif # (--with-serial) SRC_SERIAL_PAGES = \ @@ -433,6 +433,7 @@ SRC_SERIAL_PAGES = \ victronups.txt \ apcupsd-ups.txt +if ! SOME_DRIVERS if WITH_MANS MAN_SERIAL_PAGES = \ al175.8 \ @@ -476,11 +477,11 @@ MAN_SERIAL_PAGES = \ upscode2.8 \ victronups.8 \ apcupsd-ups.8 -endif +endif WITH_MANS if WITH_SERIAL man8_MANS += $(MAN_SERIAL_PAGES) -endif +endif WITH_SERIAL HTML_SERIAL_MANS = \ al175.html \ @@ -524,18 +525,21 @@ HTML_SERIAL_MANS = \ upscode2.html \ victronups.html \ apcupsd-ups.html +endif ! SOME_DRIVERS # (--with-snmp) SRC_SNMP_PAGES = snmp-ups.txt +if ! SOME_DRIVERS if WITH_MANS MAN_SNMP_PAGES = snmp-ups.8 -endif +endif WITH_MANS if WITH_SNMP man8_MANS += $(MAN_SNMP_PAGES) -endif +endif WITH_SNMP HTML_SNMP_MANS = snmp-ups.html +endif ! SOME_DRIVERS # (--with-usb) SRC_USB_LIBUSB_PAGES = \ @@ -549,6 +553,7 @@ SRC_USB_LIBUSB_PAGES = \ tripplite_usb.txt \ usbhid-ups.txt +if ! SOME_DRIVERS # NOTE: nut_usb_addvars and blazer-common are not standalone man pages if WITH_MANS MAN_USB_LIBUSB_PAGES = \ @@ -559,11 +564,11 @@ MAN_USB_LIBUSB_PAGES = \ riello_usb.8 \ tripplite_usb.8 \ usbhid-ups.8 -endif +endif WITH_MANS if WITH_USB man8_MANS += $(MAN_USB_LIBUSB_PAGES) -endif +endif WITH_USB HTML_USB_LIBUSB_MANS = \ bcmxcp_usb.html \ @@ -573,121 +578,140 @@ HTML_USB_LIBUSB_MANS = \ riello_usb.html \ tripplite_usb.html \ usbhid-ups.html +endif ! SOME_DRIVERS # (--with-serial / --with-usb) SRC_SERIAL_USB_PAGES = \ nutdrv_qx.txt +if ! SOME_DRIVERS if WITH_MANS MAN_SERIAL_USB_PAGES = \ nutdrv_qx.8 -endif +endif WITH_MANS if WITH_SERIAL man8_MANS += $(MAN_SERIAL_USB_PAGES) -else +else !WITH_SERIAL if WITH_USB man8_MANS += $(MAN_SERIAL_USB_PAGES) -endif -endif +endif WITH_USB +endif !WITH_SERIAL HTML_SERIAL_USB_MANS = \ nutdrv_qx.html +endif ! SOME_DRIVERS # (--with-neon) SRC_NETXML_PAGES = netxml-ups.txt +if ! SOME_DRIVERS if WITH_MANS MAN_NETXML_PAGES = netxml-ups.8 -endif +endif WITH_MANS if WITH_NEON man8_MANS += $(MAN_NETXML_PAGES) -endif +endif WITH_NEON HTML_NETXML_MANS = netxml-ups.html +endif ! SOME_DRIVERS # (--with-powerman) SRC_POWERMAN_PAGES = powerman-pdu.txt +if ! SOME_DRIVERS if WITH_MANS MAN_POWERMAN_PAGES = powerman-pdu.8 -endif +endif WITH_MANS if WITH_LIBPOWERMAN man8_MANS += $(MAN_POWERMAN_PAGES) -endif +endif WITH_LIBPOWERMAN HTML_POWERMAN_MANS = powerman-pdu.html +endif ! SOME_DRIVERS # (--with-ipmi) SRC_IPMIPSU_PAGES = nut-ipmipsu.txt +if ! SOME_DRIVERS if WITH_MANS MAN_IPMIPSU_PAGES = nut-ipmipsu.8 -endif +endif WITH_MANS if WITH_IPMI man8_MANS += $(MAN_IPMIPSU_PAGES) -endif +endif WITH_IPMI HTML_IPMIPSU_MANS = nut-ipmipsu.html +endif ! SOME_DRIVERS +# (--with-macosx_ups) SRC_MACOSX_PAGES = macosx-ups.txt +if ! SOME_DRIVERS if WITH_MANS MAN_MACOSX_PAGES = macosx-ups.8 -endif +endif WITH_MANS if WITH_MACOSX man8_MANS += $(MAN_MACOSX_PAGES) -endif +endif WITH_MACOSX HTML_MACOSX_MANS = macosx-ups.html +endif ! SOME_DRIVERS +# (--with-modbus) SRC_MODBUS_PAGES = phoenixcontact_modbus.txt \ generic_modbus.txt \ huawei-ups2000.txt \ socomec_jbus.txt \ adelsystem_cbi.txt + +if ! SOME_DRIVERS if WITH_MANS MAN_MODBUS_PAGES = phoenixcontact_modbus.8 \ generic_modbus.8 \ huawei-ups2000.8 \ socomec_jbus.8 \ adelsystem_cbi.8 -endif +endif WITH_MANS if WITH_MODBUS man8_MANS += $(MAN_MODBUS_PAGES) -endif +endif WITH_MODBUS HTML_MODBUS_MANS = phoenixcontact_modbus.html \ generic_modbus.html \ huawei-ups2000.html \ socomec_jbus.html \ adelsystem_cbi.html +endif ! SOME_DRIVERS +# (--with-linux_i2c) SRC_LINUX_I2C_PAGES = asem.txt pijuice.txt +if ! SOME_DRIVERS if WITH_MANS MAN_LINUX_I2C_PAGES = asem.8 pijuice.8 -endif +endif WITH_MANS if WITH_LINUX_I2C man8_MANS += $(MAN_LINUX_I2C_PAGES) -endif +endif WITH_LINUX_I2C HTML_LINUX_I2C_MANS = asem.html pijuice.html +endif ! SOME_DRIVERS +# (--with-gpio) SRC_GPIO_PAGES = generic_gpio.txt +if ! SOME_DRIVERS if WITH_MANS MAN_GPIO_PAGES = generic_gpio.8 -endif +endif WITH_MANS if WITH_GPIO man8_MANS += $(MAN_GPIO_PAGES) -endif +endif WITH_GPIO HTML_GPIO_MANS = generic_gpio.html - -# SOME_DRIVERS -endif +endif ! SOME_DRIVERS MAN_MANS = if WITH_MANS @@ -711,7 +735,7 @@ MAN_MANS += \ $(MAN_MODBUS_PAGES) \ $(MAN_LINUX_I2C_PAGES) \ $(MAN_GPIO_PAGES) -endif +endif WITH_MANS SRC_DRIVERS_PAGES = \ $(SRC_SERIAL_PAGES) \ @@ -727,8 +751,8 @@ SRC_DRIVERS_PAGES = \ $(SRC_GPIO_PAGES) if SOME_DRIVERS -# The list above probably came up empty in this case, so make sure that -# the drivers requested by configure script are documented in the build; +# (Legacy note) The list above probably came up empty in this case, so make sure +# that the drivers requested by configure script are documented in the build; # notably in the linkman-driver-names.txt file. SRC_DRIVERS_PAGES += \ $(DRIVER_MAN_LIST_PAGES) @@ -756,8 +780,8 @@ if ! SKIP_MANS EXTRA_DIST += dist dist: @echo "ERROR: Manpage building was disabled by configure script, and these pages are required for our proper 'make dist'" >&2 ; false -endif -endif +endif ! SKIP_MANS +endif ! WITH_MANS # For builds done from dist'ed sources, there may be a conflict of timestamps # between original *.txt files and pre-built manpages etc. leading to skipping From 45e40b04e1750130497530f74c504636fe5765d0 Mon Sep 17 00:00:00 2001 From: moonbuggy <3319867+moonbuggy@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:46:10 +1100 Subject: [PATCH 1154/1232] use str_to_short() instead of atoi() Signed-off-by: moonbuggy <3319867+moonbuggy@users.noreply.github.com> --- drivers/optiups.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/optiups.c b/drivers/optiups.c index 62cfa98aa4..02ec2f1182 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -487,16 +487,18 @@ void upsdrv_updateinfo(void) else if ( optimodel == OPTIMODEL_PS ) { optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) ); + short inV, outV, fV; + r = optiquery( "NV" ); - short inV = atoi ( _buf ); + str_to_short ( _buf, &inV, 10 ); r = optiquery( "OV" ); - short outV = atoi ( _buf ); + str_to_short ( _buf, &outV, 10 ); r = optiquery( "FV" ); if ( r >= 1 ) { - short f = atoi ( _buf ); - if ( f > 180 ) + str_to_short ( _buf, &fV, 10 ); + if ( fV > 180 ) { inV = inV * 2; outV = outV * 2; From e55ab1ff9ddbcaf3079a1ce2effdb36dd68a09d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 10:59:02 +0200 Subject: [PATCH 1155/1232] docs/Makefile.am: bail out of spellcheck of empty SPELLCHECK_SRC_ONE filenames Sometimes we get this: Makefile:1216: update target 'asciidoc-vars.conf' due to: asciidoc-vars.conf-spellchecked rm -f "asciidoc-vars.conf" || true ; \ echo " ASPELL Spell checking on ./"; \ ... touch "asciidoc-vars.conf" ASPELL Spell checking on ./ sed: read error on stdin: Is a directory Only seen for "asciidoc-vars.conf" so far: :; git checkout -f ; touch docs/asciidoc-vars.conf ; make spellcheck ; clear ; make dist -j 20 --trace V=1 Signed-off-by: Jim Klimov --- docs/Makefile.am | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 41a0864f63..82185719df 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -403,16 +403,26 @@ ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$) # WARNING: The percent wildcard is a GNU extension; otherwise we need # a ".txt.txt-spellchecked" type of rule and files like "README" all -# renamed to *.txt, or lots of rules for files without the extensions +# renamed to *.txt, or lots of rules for files without the extensions. +# Maybe this will get simplified with renaming to *.adoc though ;) +# # Other Makefiles have a relatively simple life, dealing with just a # few texts and name/extension patterns in their directories. #?#.txt.txt-spellchecked: Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) #%-spellchecked: % Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) #*-spellchecked */*-spellchecked: $(@:-spellchecked=) $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -# NOTE: This portable rule RELIES on just one SPELLCHECK_SRC defined +# +# NOTE: For some reason, at least GNU make insists on bogus calls: +# update target 'asciidoc-vars.conf' due to: asciidoc-vars.conf-spellchecked +# when we e.g. `make dist` after a `make spellcheck` and ended up +# with removed and touched (emptied) file, only this one so far. +# +# NOTE: This portable rule RELIES on just one SPELLCHECK_SRC defined # at a time, with an outer Makefile caller ensuring the looping: $(SPELLCHECK_BUILDDIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE) $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ + if test x"$(SPELLCHECK_SRC_ONE)" = x ; then echo "SKIP: Bogus spellcheck call for empty target filename (with make target $@)" >&2 ; exit 0; fi; \ + case "$@" in *-spellchecked) ;; *) echo "SKIP: Bogus spellcheck call for non '*-spellchecked' target filename (with make target $@)" >&2 ; exit 0;; esac; \ rm -f "$@" || true ; \ echo " ASPELL Spell checking on $(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)"; \ OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)"`" \ From 9327fa5b8dca493f312e0e306f73a19d42b97ae6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Oct 2023 11:45:41 +0200 Subject: [PATCH 1156/1232] drivers/optiups.c: Shuffle lines to keep declarations before operations Signed-off-by: Jim Klimov --- drivers/optiups.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/optiups.c b/drivers/optiups.c index 02ec2f1182..35f1005361 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -485,10 +485,10 @@ void upsdrv_updateinfo(void) if ( optimodel == OPTIMODEL_ZINTO ) optifill( _pollv_zinto, sizeof(_pollv_zinto)/sizeof(_pollv_zinto[0]) ); else if ( optimodel == OPTIMODEL_PS ) { - optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) ); - short inV, outV, fV; + optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) ); + r = optiquery( "NV" ); str_to_short ( _buf, &inV, 10 ); r = optiquery( "OV" ); From 26bf63d5af0d2ca2d457e780f4497e95f0168890 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Oct 2023 05:21:59 +0200 Subject: [PATCH 1157/1232] NEWS.adoc: optiups fixes [#2089] Signed-off-by: Jim Klimov --- NEWS.adoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index de559cf130..b640d8f1d0 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -228,6 +228,14 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - The `bestfortress` driver shutdown handling was fixed to use a non-trivial default timeout [#1820] + - The `optiups` driver only gave accurate voltage information with 120VAC + models and assumed a 12V battery when calculating capacity. There is + a protocol command that gives a (fixed) voltage which correlates with + the voltage selection DIP switches on the back of the UPS, taking into + account whether it is a 120 or 240VAC model. Likewise, now the battery + capacity fix is applied globally, based on whether or not the battery + voltage is greater than 20V. [#2089] + - GPIO drivers [#1855]: * Added a new category of drivers, using GPIO interface to locally connected devices (currently limited to 2018+ Linux libgpiod, but its architecture From 7632ef3d37a891af5532947b4626b3d86d9710af Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Oct 2023 05:30:32 +0200 Subject: [PATCH 1158/1232] tests/generic_gpio_utest.c: more fscanf() width warnings Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 2f8c0dccf1..be324d05a4 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -179,10 +179,6 @@ int main(int argc, char **argv) { fEof = 1; for(unsigned int i=0; fEof!=EOF; i++) { char fmt[16]; - do { - fEof=fscanf(testData, "%s", rules); - } while(strcmp("*", rules)); - fEof=fscanf(testData, "%s", testType); #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL #pragma GCC diagnostic push #endif @@ -198,7 +194,13 @@ int main(int argc, char **argv) { * width specifier; have to create it on the fly. */ snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(rules)-1); - fEof=fscanf(testData, "%s", rules); + do { + fEof=fscanf(testData, fmt, rules); + } while(strcmp("*", rules)); + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(testType)-1); + fEof=fscanf(testData, fmt, testType); + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(rules)-1); + fEof=fscanf(testData, fmt, rules); #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL #pragma GCC diagnostic pop #endif From 74caba405a943cd5904ccc1c12216d7181ff5ca6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 15:39:20 +0200 Subject: [PATCH 1159/1232] drivers/Makefile.am: "dist" the new sms_ser.h header Signed-off-by: Jim Klimov --- drivers/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 1f99c802e4..e24243ab91 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -349,7 +349,7 @@ dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mi main.h mge-hid.h mge-mib.h mge-utalk.h \ mge-xml.h microdowell.h microsol-apc.h microsol-common.h netvision-mib.h netxml-ups.h nut-ipmi.h oneac.h \ powercom.h powerpanel.h powerp-bin.h powerp-txt.h raritan-pdu-mib.h \ - safenet.h serial.h snmp-ups.h solis.h tripplite.h tripplite-hid.h \ + safenet.h serial.h sms_ser.h snmp-ups.h solis.h tripplite.h tripplite-hid.h \ upshandler.h usb-common.h usbhid-ups.h powercom-hid.h compaq-mib.h idowell-hid.h \ apcsmart.h apcsmart_tabs.h apcsmart-old.h apcupsd-ups.h cyberpower-mib.h riello.h openups-hid.h \ delta_ups-mib.h nutdrv_qx.h nutdrv_qx_bestups.h nutdrv_qx_blazer-common.h \ From 25cb14bad42d01e5ec203c87e92f573f5a923906 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 15:59:36 +0200 Subject: [PATCH 1160/1232] drivers/sms_ser.c: fix printf(ssize_t) Signed-off-by: Jim Klimov --- drivers/sms_ser.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c index 04ae728c81..e6aad91650 100644 --- a/drivers/sms_ser.c +++ b/drivers/sms_ser.c @@ -27,6 +27,7 @@ #include "sms_ser.h" #include "main.h" #include "serial.h" +#include "nut_stdint.h" #define ENDCHAR '\r' @@ -173,7 +174,7 @@ static int get_ups_nominal() { return -1; } - upsdebugx(3, "Get nominal Ok: received byte %lu", ret); + upsdebugx(3, "Get nominal Ok: received byte %" PRIiSIZE, ret); if (bufIn[0] == '=' || bufIn[0] == '<' || bufIn[0] == '>') { sms_parse_results(&bufIn[0], &DeviceData); @@ -205,7 +206,7 @@ static int get_ups_information() { return -1; } - upsdebugx(3, "Get information Ok: received byte %lu", ret); + upsdebugx(3, "Get information Ok: received byte %" PRIiSIZE, ret); if (bufIn[0] == ';' || bufIn[0] == ':') { sms_parse_information(&bufIn[0], &DeviceData); @@ -237,7 +238,7 @@ static int get_ups_features() { return -1; } - upsdebugx(LOG_DEBUG, "Get features Ok: received byte %lu", ret); + upsdebugx(LOG_DEBUG, "Get features Ok: received byte %" PRIiSIZE, ret); if (bufIn[0] == ';' || bufIn[0] == ':') { sms_parse_features(&bufIn[0], &DeviceData); From 768d46021a792ee7ca8f9e9a1715cd9f257628a3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 16:00:02 +0200 Subject: [PATCH 1161/1232] drivers/sms_ser.c: fix mixing of "unsigned int" and "long" delays Signed-off-by: Jim Klimov --- drivers/sms_ser.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c index e6aad91650..4dd6ef14fe 100644 --- a/drivers/sms_ser.c +++ b/drivers/sms_ser.c @@ -27,7 +27,6 @@ #include "sms_ser.h" #include "main.h" #include "serial.h" -#include "nut_stdint.h" #define ENDCHAR '\r' @@ -39,7 +38,7 @@ #define RESULT_SIZE 18 #define HUMAN_VALUES 7 -static unsigned int bootdelay = DEFAULT_BOOTDELAY; +static uint16_t bootdelay = DEFAULT_BOOTDELAY; static uint8_t bufOut[BUFFER_SIZE]; static uint8_t bufIn[BUFFER_SIZE]; static SmsData DeviceData; @@ -313,7 +312,15 @@ static int sms_instcmd(const char *cmdname, const char *extra) { } if (!strcasecmp(cmdname, "shutdown.reboot")) { - long delay = extra ? strtol(extra, NULL, bootdelay) : bootdelay; + uint16_t delay = bootdelay; + if (extra) { + long ldelay = strtol(extra, NULL, bootdelay); + if (ldelay >= 0 && (intmax_t)ldelay < (intmax_t)UINT16_MAX) { + delay = (uint16_t)ldelay; + } else { + upsdebugx(3, "tried to set up extra shutdown.reboot delay ut it was out of range, keeping default"); + } + } length = sms_prepare_shutdown_nsec(&bufOut[0], delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { From 9abce86a562bfa0a308c90f4d36dc71ba7fad5e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 16:00:25 +0200 Subject: [PATCH 1162/1232] drivers/sms_ser.c: fix use of methods without a prototype - make them static Signed-off-by: Jim Klimov --- drivers/sms_ser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c index 4dd6ef14fe..6ca7f80d71 100644 --- a/drivers/sms_ser.c +++ b/drivers/sms_ser.c @@ -51,7 +51,7 @@ upsdrv_info_t upsdrv_info = { DRV_BETA, {NULL}}; -void sms_parse_features(uint8_t *rawvalues, SmsData *results) { +static void sms_parse_features(uint8_t *rawvalues, SmsData *results) { char tbattery[6]; char frequency[4]; @@ -76,7 +76,7 @@ void sms_parse_features(uint8_t *rawvalues, SmsData *results) { results->frequency = atoi(frequency); } -void sms_parse_information(uint8_t *rawvalues, SmsData *results) { +static void sms_parse_information(uint8_t *rawvalues, SmsData *results) { /* Count from 1 to ignore first char and remove 2 from BUFFER_SIZE * to compensate the start and ignore '\r' from end. */ memset(results->model, 0, sizeof(results->model)); From dd40841b36d7c5f2bdfe6d1ce25a09b1adfa408e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 16:01:51 +0200 Subject: [PATCH 1163/1232] Revert "drivers/sms_ser.c: fix use of methods without a prototype - make them static" This reverts commit 8de11079a80754af38ad67524009003028a6912e to try a different approach. Signed-off-by: Jim Klimov --- drivers/sms_ser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c index 6ca7f80d71..4dd6ef14fe 100644 --- a/drivers/sms_ser.c +++ b/drivers/sms_ser.c @@ -51,7 +51,7 @@ upsdrv_info_t upsdrv_info = { DRV_BETA, {NULL}}; -static void sms_parse_features(uint8_t *rawvalues, SmsData *results) { +void sms_parse_features(uint8_t *rawvalues, SmsData *results) { char tbattery[6]; char frequency[4]; @@ -76,7 +76,7 @@ static void sms_parse_features(uint8_t *rawvalues, SmsData *results) { results->frequency = atoi(frequency); } -static void sms_parse_information(uint8_t *rawvalues, SmsData *results) { +void sms_parse_information(uint8_t *rawvalues, SmsData *results) { /* Count from 1 to ignore first char and remove 2 from BUFFER_SIZE * to compensate the start and ignore '\r' from end. */ memset(results->model, 0, sizeof(results->model)); From 4e439efd837105b9c8cff23cb0075c6ecbaf9230 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 16:03:11 +0200 Subject: [PATCH 1164/1232] drivers/sms_ser.c: fix use of methods without a prototype - expose in header Signed-off-by: Jim Klimov --- drivers/sms_ser.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/sms_ser.h b/drivers/sms_ser.h index a47c863f27..282ada7f1e 100644 --- a/drivers/sms_ser.h +++ b/drivers/sms_ser.h @@ -54,11 +54,14 @@ typedef struct { float outputHz; /* output.frequency */ float batterylevel; /* battery.charge (batterylevel < 100 ? battery.charger.status = charging if onacpower/discharging if onbattery : resting) * battery.voltage = (voltageBattery * batterylevel) / 100) - */ + */ float temperatureC; /* ups.temperature */ } SmsData; +void sms_parse_features(uint8_t *rawvalues, SmsData *results); +void sms_parse_information(uint8_t *rawvalues, SmsData *results); void sms_parse_results(uint8_t* rawvalues, SmsData* results); + uint8_t sms_prepare_get_status(uint8_t* buffer); uint8_t sms_prepare_get_information(uint8_t* buffer); uint8_t sms_prepare_get_features(uint8_t* buffer); From dfbf5e918c6d85b66f629bd598069cc380e435c6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Oct 2023 15:54:11 +0200 Subject: [PATCH 1165/1232] Jenkinsfile-dynamatrix: enable tracing for fightwarn branches Signed-off-by: Jim Klimov --- Jenkinsfile-dynamatrix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index 0d08fa9c98..c2f591a1c7 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -55,8 +55,12 @@ import org.nut.dynamatrix.*; dynacfgPipeline.disableSlowBuildCIBuild_QEMU = false } - dynacfgPipeline.traceBuildShell_configureEnvvars = false// true - dynacfgPipeline.traceBuildShell = false //true + dynacfgPipeline.traceBuildShell_configureEnvvars = false // true + dynacfgPipeline.traceBuildShell = false // true + if ( env?.BRANCH_NAME ==~ /.*fightwarn.*/ ) { + dynacfgPipeline.traceBuildShell_configureEnvvars = true // false + dynacfgPipeline.traceBuildShell = true // false + } dynacfgPipeline.failFast = //true // false From ba9d3da03f2dbcc3735d45afde1821e407581574 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 16:47:34 +0200 Subject: [PATCH 1166/1232] Jenkinsfile-dynamatrix: warn about lack of dynacfgPipeline.configureEnvvars when we "Investigate envvars" Signed-off-by: Jim Klimov --- Jenkinsfile-dynamatrix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index c2f591a1c7..2a804da0c4 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -253,7 +253,8 @@ import org.nut.dynamatrix.*; def dsbcClone = dsbc.clone() stage('Investigate envvars (Autotools DEBUG)') { - echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + + (dynacfgPipeline?.configureEnvvars ? "" : " (note: has no dynacfgPipeline.configureEnvvars)") // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true @@ -282,7 +283,8 @@ set | sort -n """ def dsbcClone = dsbc.clone() stage('Investigate envvars (CI_Build DEBUG)') { - echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + + (dynacfgPipeline?.configureEnvvars ? "" : " (note: has no dynacfgPipeline.configureEnvvars)") // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true From 9b98822a38436207f8d7f40354da3fd8e005dc02 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 7 Oct 2023 15:31:56 +0200 Subject: [PATCH 1167/1232] tests/generic_gpio_utest.c: avoid NULL deref in printf() on some platforms Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index be324d05a4..93da57399f 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -284,7 +284,9 @@ int main(int argc, char **argv) { printf("%s %s test rule %u [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", pass_fail[failed], testType, i, rules, upsStatus, chargeStatus, charge, chargeLow, - currUpsStatus, currChargerStatus, currCharge); + NUT_STRARG(currUpsStatus), + NUT_STRARG(currChargerStatus), + NUT_STRARG(currCharge)); if(!failed) { cases_passed++; } else { From 1d49667dddfb809c88b8a80e69af2259c94be300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20W=20Baul=C3=A9?= Date: Sun, 8 Oct 2023 11:46:05 -0300 Subject: [PATCH 1168/1232] Add man file and update Makefile.am MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex W Baulé --- docs/man/Makefile.am | 3 +++ docs/man/sms_ser.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 docs/man/sms_ser.txt diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 2326ea1c1d..083f52c036 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -425,6 +425,7 @@ SRC_SERIAL_PAGES = \ powerpanel.txt \ rhino.txt \ riello_ser.txt \ + sms_ser.txt \ safenet.txt \ solis.txt \ tripplite.txt \ @@ -470,6 +471,7 @@ MAN_SERIAL_PAGES = \ powerpanel.8 \ rhino.8 \ riello_ser.8 \ + sms_ser.8 \ safenet.8 \ solis.8 \ tripplite.8 \ @@ -518,6 +520,7 @@ HTML_SERIAL_MANS = \ powerpanel.html \ rhino.html \ riello_ser.html \ + sms_ser.html \ safenet.html \ solis.html \ tripplite.html \ diff --git a/docs/man/sms_ser.txt b/docs/man/sms_ser.txt new file mode 100644 index 0000000000..bc18b87c38 --- /dev/null +++ b/docs/man/sms_ser.txt @@ -0,0 +1,43 @@ +SMS_SER(8) +========== + +NAME +---- + +sms_ser - Driver for SMS UPS Protocol 1Phase. + +SYNOPSIS +-------- + +*sms_ser* -h + +*sms_ser* -a 'UPS_NAME' ['OPTIONS'] + +NOTE: This man page only documents the hardware-specific features of the +sms_ser driver. For information about the core driver, see +linkman:nutupsdrv[8] and on doc/sms-brazil-protocol.txt. + +SUPPORTED HARDWARE +------------------ + +sms_ser supports only the sms 1phase SMS Product, get from `monofasico.xml` file. +Other SMS protocols for another products are not supported. + + +AUTHOR +------ + +Alex W. Baulé + +SEE ALSO +-------- + +The core driver +~~~~~~~~~~~~~~~~ + +linkman:nutupsdrv[8] + +Internet resources +~~~~~~~~~~~~~~~~~~ + +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ From a457355a38fee691b386d86104db176874cfd4dc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Oct 2023 16:59:00 +0200 Subject: [PATCH 1169/1232] Jenkinsfile-dynamatrix: hush down groovy debug verbosity, use BRANCH_NAME patterns as the default toggle to be loud and slow Signed-off-by: Jim Klimov --- Jenkinsfile-dynamatrix | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index 2a804da0c4..c8fcb5b80d 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -57,10 +57,14 @@ import org.nut.dynamatrix.*; dynacfgPipeline.traceBuildShell_configureEnvvars = false // true dynacfgPipeline.traceBuildShell = false // true - if ( env?.BRANCH_NAME ==~ /.*fightwarn.*/ ) { - dynacfgPipeline.traceBuildShell_configureEnvvars = true // false - dynacfgPipeline.traceBuildShell = true // false - } + + //if (false) // <<< (Un-)comment away in select runs/branches + //if (true) // <<< (Un-)comment away in select runs/branches + if ( env?.BRANCH_NAME ==~ /.*fightwarn-verbose.*/ ) + { + dynacfgPipeline.traceBuildShell_configureEnvvars = true // false + dynacfgPipeline.traceBuildShell = true // false + } dynacfgPipeline.failFast = //true // false @@ -1272,14 +1276,15 @@ def stageNameFunc_ShellcheckCustom(DynamatrixSingleBuildConfig dsbc) { /////////////////////////////////////////////////////////////////////////// - // Hacky big switch for a max debug option - if (true) - if (false) - { +// Hacky big switch for a max debug option +//if (true) // <<< (Un-)comment away in select runs/branches +//if (false) // <<< (Un-)comment away in select runs/branches +if ( env?.BRANCH_NAME ==~ /.*verbose.*/ ) +{ dynamatrixGlobalState.enableDebugTrace = true dynamatrixGlobalState.enableDebugErrors = true dynamatrixGlobalState.enableDebugMilestones = true dynamatrixGlobalState.enableDebugMilestonesDetails = true - } +} dynamatrixPipeline(dynacfgBase, dynacfgPipeline) From 304ad6ecddef25074d293cd1c8bd691356033497 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Oct 2023 18:23:18 +0200 Subject: [PATCH 1170/1232] Update nut.dict for PR #2090 Signed-off-by: Jim Klimov --- docs/nut.dict | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index d907cce2cb..ed515604e3 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3243 utf-8 +personal_ws-1.1 en 3246 utf-8 AAS ABI ACFAIL @@ -126,6 +126,7 @@ BattTstFail BatteryA BatteryB BaudRt +Baulé BayTech BeepTone Belkin's @@ -1632,6 +1633,7 @@ boostvoolts bootable bp br +brazil bsd bsv bt @@ -2392,6 +2394,7 @@ modbus modelname modprobe monmaster +monofasico monpasswd monslave monuser From 935fef2835adf28dcd895b970141e92017595851 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Oct 2023 18:41:09 +0200 Subject: [PATCH 1171/1232] drivers/main.c: follow TOCTOU analysis suggestions about file permissions check and enforcement Signed-off-by: Jim Klimov --- drivers/main.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index cefb6cdd5c..919355fda9 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -2257,6 +2257,12 @@ int main(int argc, char **argv) ) { #ifndef WIN32 int allOk = 1; + /* Use file descriptor, not name, to first check and then manipulate permissions: + * https://cwe.mitre.org/data/definitions/367.html + * https://wiki.sei.cmu.edu/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification + */ + TYPE_FD fd = ERROR_FD; + /* Tune group access permission to the pipe, * so that upsd can access it (using the * specified or retained default group): @@ -2273,18 +2279,28 @@ int main(int argc, char **argv) group, strerror(errno) ); allOk = 0; + goto sockname_ownership_finished; } else { struct stat statbuf; mode_t mode; - if (stat(sockname, &statbuf)) { + if (INVALID_FD((fd = open(sockname, O_RDWR | O_APPEND)))) { + upsdebugx(1, "WARNING: opening socket file for stat/chown failed: %s", + strerror(errno) + ); + allOk = 0; + /* Can not proceed with ops below */ + goto sockname_ownership_finished; + } + + if (fstat(fd, &statbuf)) { upsdebugx(1, "WARNING: stat for chown failed: %s", strerror(errno) ); allOk = 0; } else { /* Here we do a portable chgrp() essentially: */ - if (chown(sockname, statbuf.st_uid, grp->gr_gid)) { + if (fchown(fd, statbuf.st_uid, grp->gr_gid)) { upsdebugx(1, "WARNING: chown failed: %s", strerror(errno) ); @@ -2293,7 +2309,7 @@ int main(int argc, char **argv) } /* Refresh file info */ - if (stat(sockname, &statbuf)) { + if (fstat(fd, &statbuf)) { /* Logically we'd fail chown above if file * does not exist or is not accessible */ upsdebugx(1, "WARNING: stat for chmod failed: %s", @@ -2305,7 +2321,7 @@ int main(int argc, char **argv) mode = statbuf.st_mode; mode |= S_IWGRP; mode |= S_IRGRP; - if (chmod(sockname, mode)) { + if (fchmod(fd, mode)) { upsdebugx(1, "WARNING: chmod failed: %s", strerror(errno) ); @@ -2314,6 +2330,12 @@ int main(int argc, char **argv) } } +sockname_ownership_finished: + if (VALID_FD(fd)) { + close(fd); + fd = ERROR_FD; + } + if (allOk) { upsdebugx(1, "Group access for this driver successfully fixed"); } else { From 4fd257e9a82d73524cd3a1f44c8b6fc65ead0e3a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Oct 2023 23:07:17 +0200 Subject: [PATCH 1172/1232] tests/nutlogtest.c: revise include statements Signed-off-by: Jim Klimov --- tests/nutlogtest.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/nutlogtest.c b/tests/nutlogtest.c index 5aaad31ea8..b8b51dcf77 100644 --- a/tests/nutlogtest.c +++ b/tests/nutlogtest.c @@ -3,7 +3,7 @@ * do not crash). * * Copyright (C) - * 2020 Jim Klimov + * 2020-2023 Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "config.h" #include "common.h" int main(void) { From 1aaff29c6706228a1fcae1c933e611f8b6aad441 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Oct 2023 00:09:53 +0200 Subject: [PATCH 1173/1232] tests/Makefile.am: refer to nutlogtest$(EXEEXT) for clarity in dependencies Signed-off-by: Jim Klimov --- tests/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index c063f6dca2..da1c03e4bf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,9 +24,9 @@ nutlogtest_LDADD = $(top_builddir)/common/libcommon.la if REQUIRE_NUT_STRARG check_SCRIPTS += nutlogtest-nofail.sh -CLEANFILES += nutlogtest-nofail.sh nutlogtest +CLEANFILES += nutlogtest-nofail.sh nutlogtest$(EXEEXT) nutlogtest -nutlogtest-nofail.sh: nutlogtest +nutlogtest-nofail.sh: nutlogtest$(EXEEXT) @echo '#!/bin/sh' > $@ @echo 'echo "WARNING: Your C library requires workarounds to print NULL values!" >&2' >> $@ @echo 'echo "If nutlogtest below, or generally some NUT program, crashes with" >&2' >> $@ @@ -37,7 +37,7 @@ nutlogtest-nofail.sh: nutlogtest # NOTE: Keep the line above empty! else -TESTS += nutlogtest +TESTS += nutlogtest$(EXEEXT) endif TESTS += nuttimetest From ade40291a01cdb85cf798ca4cd20ec3431795502 Mon Sep 17 00:00:00 2001 From: "Clappier, Eric" Date: Tue, 10 Oct 2023 09:03:46 +0200 Subject: [PATCH 1174/1232] Fix issues in compaq mib --- drivers/compaq-mib.c | 55 ++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/compaq-mib.c b/drivers/compaq-mib.c index 4fdd9f9435..7120797998 100644 --- a/drivers/compaq-mib.c +++ b/drivers/compaq-mib.c @@ -30,7 +30,7 @@ #include "compaq-mib.h" -#define CPQPOWER_MIB_VERSION "1.66" +#define CPQPOWER_MIB_VERSION "1.67" #define DEFAULT_ONDELAY "30" #define DEFAULT_OFFDELAY "20" @@ -192,11 +192,11 @@ static snmp_info_t cpqpower_mib[] = { { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_FIRMREV, "", 0, NULL }, { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_AGENTREV, "", 0, NULL }, { "ups.load", 0, 1.0, CPQPOWER_OID_LOAD_LEVEL, "", 0, NULL }, - { "ups.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER, "", SU_OUTPUT_1, NULL }, - { "ups.realpower", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.3.0", "", SU_OUTPUT_1, NULL }, - { "ups.L1.realpower", 0, 0.1, CPQPOWER_OID_OUT_POWER ".1", "", SU_OUTPUT_3, NULL }, - { "ups.L2.realpower", 0, 0.1, CPQPOWER_OID_OUT_POWER ".2", "", SU_OUTPUT_3, NULL }, - { "ups.L3.realpower", 0, 0.1, CPQPOWER_OID_OUT_POWER ".3", "", SU_OUTPUT_3, NULL }, + { "ups.realpower.nominal", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.3.0", "", SU_OUTPUT_1, NULL }, + { "ups.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER ".1", "", SU_OUTPUT_1, NULL }, + { "ups.L1.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER ".1", "", SU_OUTPUT_3, NULL }, + { "ups.L2.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER ".2", "", SU_OUTPUT_3, NULL }, + { "ups.L3.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER ".3", "", SU_OUTPUT_3, NULL }, { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_POWER_STATUS, "OFF", SU_STATUS_PWR, cpqpower_pwr_info }, { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_BATT_STATUS, "", SU_STATUS_PWR, cpqpower_battery_abm_status }, /* The next two lines are no longer supported by MIB ver. 1.76 (Github issue 118) @@ -240,44 +240,35 @@ static snmp_info_t cpqpower_mib[] = { /* Input page */ { "input.phases", 0, 1.0, CPQPOWER_OID_IN_LINES, "", 0, NULL }, -/* { "input.phase", 0, 1.0, CPQPOWER_OID_IN_PHASE, "", SU_OUTPUT_1, NULL }, */ { "input.frequency", 0, 0.1, CPQPOWER_OID_IN_FREQ , "", 0, NULL }, - { "input.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE, "", SU_OUTPUT_1, NULL }, - { "input.voltage", 0, 1.0, ".1.3.6.1.4.1.232.165.3.3.4.1.2.1", "", SU_OUTPUT_1, NULL }, - { "input.voltage.nominal", ST_FLAG_RW | ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.9.2.0", "", SU_OUTPUT_1, NULL }, + { "input.voltage.nominal", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.2.0", "", 0, NULL }, + { "input.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE ".1", "", SU_OUTPUT_1, NULL }, { "input.L1-N.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE ".1", "", SU_INPUT_3, NULL }, { "input.L2-N.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE ".2", "", SU_INPUT_3, NULL }, { "input.L3-N.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE ".3", "", SU_INPUT_3, NULL }, - { "input.current", 0, 0.1, CPQPOWER_OID_IN_CURRENT, "", SU_OUTPUT_1, NULL }, - { "input.current", 0, 0.1, ".1.3.6.1.4.1.232.165.3.3.4.1.3.1", "", SU_OUTPUT_1, NULL }, - - { "input.L1.current", 0, 0.1, CPQPOWER_OID_IN_CURRENT ".1", "", SU_INPUT_3, NULL }, - { "input.L2.current", 0, 0.1, CPQPOWER_OID_IN_CURRENT ".2", "", SU_INPUT_3, NULL }, - { "input.L3.current", 0, 0.1, CPQPOWER_OID_IN_CURRENT ".3", "", SU_INPUT_3, NULL }, - { "input.realpower", 0, 0.1, CPQPOWER_OID_IN_POWER, "", SU_OUTPUT_1, NULL }, - { "input.L1.realpower", 0, 0.1, CPQPOWER_OID_IN_POWER ".1", "", SU_INPUT_3, NULL }, - { "input.L2.realpower", 0, 0.1, CPQPOWER_OID_IN_POWER ".2", "", SU_INPUT_3, NULL }, - { "input.L3.realpower", 0, 0.1, CPQPOWER_OID_IN_POWER ".3", "", SU_INPUT_3, NULL }, + { "input.current", 0, 1.0, CPQPOWER_OID_IN_CURRENT ".1", "", SU_OUTPUT_1, NULL }, + { "input.L1.current", 0, 1.0, CPQPOWER_OID_IN_CURRENT ".1", "", SU_INPUT_3, NULL }, + { "input.L2.current", 0, 1.0, CPQPOWER_OID_IN_CURRENT ".2", "", SU_INPUT_3, NULL }, + { "input.L3.current", 0, 1.0, CPQPOWER_OID_IN_CURRENT ".3", "", SU_INPUT_3, NULL }, + { "input.realpower", 0, 1.0, CPQPOWER_OID_IN_POWER ".1", "", SU_OUTPUT_1, NULL }, + { "input.L1.realpower", 0, 1.0, CPQPOWER_OID_IN_POWER ".1", "", SU_INPUT_3, NULL }, + { "input.L2.realpower", 0, 1.0, CPQPOWER_OID_IN_POWER ".2", "", SU_INPUT_3, NULL }, + { "input.L3.realpower", 0, 1.0, CPQPOWER_OID_IN_POWER ".3", "", SU_INPUT_3, NULL }, { "input.quality", 0, 1.0, CPQPOWER_OID_IN_LINEBADS, "", 0, NULL }, /* Output page */ { "output.phases", 0, 1.0, CPQPOWER_OID_OUT_LINES, "", 0, NULL }, -/* { "output.phase", 0, 1.0, CPQPOWER_OID_OUT_PHASE, "", SU_OUTPUT_1, NULL }, */ + { "output.frequency.nominal", 0, 0.1, ".1.3.6.1.4.1.232.165.3.9.4.0", "", 0, NULL }, { "output.frequency", 0, 0.1, CPQPOWER_OID_OUT_FREQUENCY, "", 0, NULL }, - /* FIXME: handle multiplier (0.1 there) */ - { "output.frequency.nominal", ST_FLAG_RW | ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.9.4.0", "", SU_OUTPUT_1, NULL }, - { "output.voltage", 0, 1.0, CPQPOWER_OID_OUT_VOLTAGE, "", SU_OUTPUT_1, NULL }, - { "output.voltage", 0, 1.0, ".1.3.6.1.4.1.232.165.3.4.4.1.2.1", "", SU_OUTPUT_1, NULL }, - { "output.voltage.nominal", ST_FLAG_RW | ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.9.1.0", "", SU_OUTPUT_1, NULL }, + { "output.voltage.nominal", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.1.0", "", 0, NULL }, + { "output.voltage", 0, 1.0, CPQPOWER_OID_OUT_VOLTAGE ".1", "", SU_OUTPUT_1, NULL }, { "output.L1-N.voltage", 0, 1.0, CPQPOWER_OID_OUT_VOLTAGE ".1", "", SU_OUTPUT_3, NULL }, { "output.L2-N.voltage", 0, 1.0, CPQPOWER_OID_OUT_VOLTAGE ".2", "", SU_OUTPUT_3, NULL }, { "output.L3-N.voltage", 0, 1.0, CPQPOWER_OID_OUT_VOLTAGE ".3", "", SU_OUTPUT_3, NULL }, - { "output.current", 0, 0.1, CPQPOWER_OID_OUT_CURRENT, "", SU_OUTPUT_1, NULL }, - { "output.current", 0, 0.1, ".1.3.6.1.4.1.232.165.3.4.4.1.3.1", "", SU_OUTPUT_1, NULL }, - /* { "output.realpower", 0, 1.0, ".1.3.6.1.4.1.232.165.3.4.4.1.4", "", SU_OUTPUT_1, NULL }, */ - { "output.L1.current", 0, 0.1, CPQPOWER_OID_OUT_CURRENT ".1", "", SU_OUTPUT_3, NULL }, - { "output.L2.current", 0, 0.1, CPQPOWER_OID_OUT_CURRENT ".2", "", SU_OUTPUT_3, NULL }, - { "output.L3.current", 0, 0.1, CPQPOWER_OID_OUT_CURRENT ".3", "", SU_OUTPUT_3, NULL }, + { "output.current", 0, 1.0, CPQPOWER_OID_OUT_CURRENT ".1", "", SU_OUTPUT_1, NULL }, + { "output.L1.current", 0, 1.0, CPQPOWER_OID_OUT_CURRENT ".1", "", SU_OUTPUT_3, NULL }, + { "output.L2.current", 0, 1.0, CPQPOWER_OID_OUT_CURRENT ".2", "", SU_OUTPUT_3, NULL }, + { "output.L3.current", 0, 1.0, CPQPOWER_OID_OUT_CURRENT ".3", "", SU_OUTPUT_3, NULL }, /* FIXME: what to map with these? * Name/OID: upsConfigLowOutputVoltageLimit.0; Value (Integer): 160 From a816677fcf0e2d7a9e8babdb82e1d8354ef19515 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Oct 2023 23:14:51 +0200 Subject: [PATCH 1175/1232] data/driver.list.in: add CP1350PFCLCD Signed-off-by: Jim Klimov --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index d1eb3951e2..8d9b56e0b0 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -236,6 +236,7 @@ "Cyber Power Systems" "ups" "3" "CP1350AVRLCD" "USB" "usbhid-ups" "Cyber Power Systems" "ups" "3" "CP1500AVRLCD" "USB" "usbhid-ups" "Cyber Power Systems" "ups" "3" "CP850PFCLCD" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/605 +"Cyber Power Systems" "ups" "3" "CP1350PFCLCD" "USB" "usbhid-ups" # https://alioth-lists.debian.net/pipermail/nut-upsuser/2023-October/013441.html "Cyber Power Systems" "ups" "3" "CP1500PFCLCD" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/cp1500pfclcd/ https://github.com/networkupstools/nut/issues/520 "Cyber Power Systems" "ups" "3" "CPJ500" "USB" "usbhid-ups" # https://www.cyberpower.com/jp/ja/product/sku/cpj500#downloads https://github.com/networkupstools/nut/issues/1403 "Cyber Power Systems" "ups" "3" "CP900AVR" "USB" "usbhid-ups" From 1a153ec3072e6e20887aadcebb3eb71c67a93270 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Oct 2023 22:28:14 +0000 Subject: [PATCH 1176/1232] tests/generic_gpio_utest.c: avoid "error: variable might be clobbered by longjmp or vfork" [#2092] Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 93da57399f..329f609a44 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -249,10 +249,15 @@ int main(int argc, char **argv) { char chargeLow[256]; char charge[256]; struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); - int failed = 0; - const char *currUpsStatus=NULL; - const char *currChargerStatus=NULL; - const char *currCharge=NULL; + + /* "volatile" trickery to avoid the likes of: + * error: variable 'failed' might be clobbered by 'longjmp' or 'vfork' [-Werror=clobbered] + * due to presence of setjmp(). + */ + int volatile failed = 0; + const char * volatile currUpsStatus = NULL; + const char * volatile currChargerStatus = NULL; + const char * volatile currCharge = NULL; get_ups_rules(upsfdtest, (unsigned char *)rules); upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); From a55bcd31d42ff221d5ebdcc071f6f0c1bda382bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Oct 2023 22:40:51 +0000 Subject: [PATCH 1177/1232] tests/generic_gpio_utest.c: cosmetic fixes Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 84 +++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 329f609a44..07a06e6d9f 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -55,48 +55,49 @@ void getWithoutUnderscores(char *var) { #define DESCRIPTION "modem and DNS server UPS" int get_test_status(struct gpioups_t *result, int on_fail_path) { - int expecting_failure; - int upsLinesCount; /* no of lines used in rules */ - int upsMaxLine; /* maximum line number referenced in rules */ - int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ - char stateName[12]; /* NUT state name for rules in cRules */ - int subCount; /* element count in translated rules subitem */ - int ruleInt; + int expecting_failure; + int upsLinesCount; /* no of lines used in rules */ + int upsMaxLine; /* maximum line number referenced in rules */ + int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ + char stateName[12]; /* NUT state name for rules in cRules */ + int subCount; /* element count in translated rules subitem */ + int ruleInt; + int i, j; - fEof=fscanf(testData, "%d", &expecting_failure); - if(on_fail_path) { + fEof = fscanf(testData, "%d", &expecting_failure); + if (on_fail_path) { if(expecting_failure) cases_failed++; else cases_passed++; return expecting_failure; } - if(!expecting_failure) { + if (!expecting_failure) { cases_failed++; printf("expecting case to fail\n"); return 1; } - fEof=fscanf(testData, "%d", &upsLinesCount); - if(result->upsLinesCount!=upsLinesCount) { + fEof = fscanf(testData, "%d", &upsLinesCount); + if (result->upsLinesCount!=upsLinesCount) { cases_failed++; printf("expecting upsLinesCount %d, got %d\n", upsLinesCount, result->upsLinesCount); return 1; } - fEof=fscanf(testData, "%d", &upsMaxLine); - if(result->upsMaxLine!=upsMaxLine) { + fEof = fscanf(testData, "%d", &upsMaxLine); + if (result->upsMaxLine!=upsMaxLine) { cases_failed++; printf("expecting rulesCount %d, got %d\n", upsMaxLine, result->upsMaxLine); return 1; } - fEof=fscanf(testData, "%d", &rulesCount); - if(result->rulesCount!=rulesCount) { + fEof = fscanf(testData, "%d", &rulesCount); + if (result->rulesCount!=rulesCount) { cases_failed++; printf("expecting rulesCount %d, got %d\n", rulesCount, result->rulesCount); return 1; } - for(int i=0; irulesCount; i++) { + for (i=0; irulesCount; i++) { fEof=fscanf(testData, "%s", stateName); if(!strcmp(result->rules[i]->stateName,stateName)) { cases_failed++; @@ -109,7 +110,7 @@ int get_test_status(struct gpioups_t *result, int on_fail_path) { printf("expecting subCount %d, got %d for rule %d\n", result->rules[i]->subCount, subCount, i); return 1; } - for(int j=0; jrules[i]->cRules[j]!=ruleInt) { cases_failed++; @@ -125,12 +126,12 @@ int get_test_status(struct gpioups_t *result, int on_fail_path) { void exit(int code) { - if (!done) { - longjmp(env_buffer, 1); - } - else { - _exit(code); - } + if (!done) { + longjmp(env_buffer, 1); + } + else { + _exit(code); + } } int main(int argc, char **argv) { @@ -138,7 +139,8 @@ int main(int argc, char **argv) { char rules[128]; char testType[128]; char testDescFileNameBuf[LARGEBUF]; - char *testDescFileName="generic_gpio_test.txt"; + char *testDescFileName = "generic_gpio_test.txt"; + unsigned int i; test_with_exit=0; @@ -177,7 +179,7 @@ int main(int argc, char **argv) { cases_passed=0; cases_failed=0; fEof = 1; - for(unsigned int i=0; fEof!=EOF; i++) { + for (i=0; fEof!=EOF; i++) { char fmt[16]; #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL #pragma GCC diagnostic push @@ -221,15 +223,17 @@ int main(int argc, char **argv) { int expectedStateValue; int calculatedStateValue; struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + int j; + get_ups_rules(upsfdtest, (unsigned char *)rules); upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); - for(int j=0; jupsLinesCount; j++) { + for (j=0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } - for(int j=0; jrulesCount; j++) { + for (j=0; j < upsfdtest->rulesCount; j++) { fEof=fscanf(testData, "%d", &expectedStateValue); calculatedStateValue=calc_rule_states(upsfdtest->upsLinesStates, upsfdtest->rules[j]->cRules, upsfdtest->rules[j]->subCount, 0); - if(expectedStateValue==calculatedStateValue) { + if (expectedStateValue==calculatedStateValue) { printf("%s %s test rule %u [%s]\n", pass_fail[0], testType, i, rules); cases_passed++; } else { @@ -249,6 +253,7 @@ int main(int argc, char **argv) { char chargeLow[256]; char charge[256]; struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + int j; /* "volatile" trickery to avoid the likes of: * error: variable 'failed' might be clobbered by 'longjmp' or 'vfork' [-Werror=clobbered] @@ -261,17 +266,17 @@ int main(int argc, char **argv) { get_ups_rules(upsfdtest, (unsigned char *)rules); upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); - for(int j=0; jupsLinesCount; j++) { + for (j = 0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } getWithoutUnderscores(upsStatus); getWithoutUnderscores(chargeStatus); getWithoutUnderscores(chargeLow); getWithoutUnderscores(charge); - if(strcmp(chargeLow, ".")) + if (strcmp(chargeLow, ".")) dstate_setinfo("battery.charge.low", "%s", chargeLow); jmp_result = setjmp(env_buffer); - if(jmp_result) { + if (jmp_result) { failed=1; generic_gpio_close(upsfdtest); } else { @@ -292,7 +297,7 @@ int main(int argc, char **argv) { NUT_STRARG(currUpsStatus), NUT_STRARG(currChargerStatus), NUT_STRARG(currCharge)); - if(!failed) { + if (!failed) { cases_passed++; } else { cases_failed++; @@ -352,12 +357,13 @@ int main(int argc, char **argv) { !dstate_getinfo("device.description") || strcmp(dstate_getinfo("device.description"), DESCRIPTION)) failed=1; } if(!strcmp(subType, "updateinfo")) { - for(int k=0; kupsLinesCount; k++) { + int k; + for(k=0; kupsLinesCount; k++) { gpioupsfd->upsLinesStates[k]=-1; } if(expecting_failure) setNextLinesReadToFail(); upsdrv_updateinfo(); - for(int k=0; kupsLinesCount && failed!=1; k++) { + for(k=0; kupsLinesCount && failed!=1; k++) { if(gpioupsfd->upsLinesStates[k]<0) failed=1; } } @@ -365,17 +371,19 @@ int main(int argc, char **argv) { } printf("%s %s %s test rule %u [%s] %s %d\n", pass_fail[failed], testType, subType, i, rules, chipNameLocal, expecting_failure); - if(!failed) { + if (!failed) { cases_passed++; } else { cases_failed++; } - vartab_free(); vartab_h = NULL; + vartab_free(); + vartab_h = NULL; } } } - printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); + printf("test_rules completed. Total cases %d, passed %d, failed %d\n", + cases_passed+cases_failed, cases_passed, cases_failed); fclose(testData); done = 1; } From ce37a62bf50e2b3b14b34ba37c6e79ae99d28a52 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Oct 2023 23:14:29 +0000 Subject: [PATCH 1178/1232] clients/upsclient.c, server/netssl.c, m4/ax_c_pragmas.m4: hush -Wcast-function-type-strict due to void* vs. practical pointers with NSS method pointers [#2084] Signed-off-by: Jim Klimov --- clients/upsclient.c | 7 +++++++ m4/ax_c_pragmas.m4 | 27 +++++++++++++++++++++++++++ server/netssl.c | 7 +++++++ 3 files changed, 41 insertions(+) diff --git a/clients/upsclient.c b/clients/upsclient.c index 22604a9ada..74290cd26f 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -909,6 +909,10 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert) return -1; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +#endif if (verifycert) { status = SSL_AuthCertificateHook(ups->ssl, (SSLAuthCertificate)AuthCertificate, CERT_GetDefaultCertDB()); @@ -938,6 +942,9 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert) nss_error("upscli_sslinit / SSL_HandshakeCallback"); return -1; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic pop +#endif cert = upscli_find_host_cert(ups->host); if (cert != NULL && cert->certname != NULL) { diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index 14ecd596d3..070d82beee 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -674,6 +674,33 @@ dnl ### [CFLAGS="${CFLAGS_SAVED} -Werror=pragmas -Werror=unknown-warning" AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_ALIGN_BESIDEFUNC], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-align" (outside functions)]) ]) + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wcast-function-type-strict"], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[void func(void) { +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +} +]], [])], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict=yes], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict=no] + )] + ) + AS_IF([test "$ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict" = "yes"],[ + AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-function-type-strict"]) + ]) + + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wcast-function-type-strict" (outside functions)], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#pragma GCC diagnostic ignored "-Wcast-function-type-strict"]], [])], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc=yes], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc=no] + )] + ) + AS_IF([test "$ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc" = "yes"],[ + AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT_BESIDEFUNC], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-function-type-strict" (outside functions)]) + ]) + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wstrict-prototypes"], [ax_cv__pragma__gcc__diags_ignored_strict_prototypes], [AC_COMPILE_IFELSE( diff --git a/server/netssl.c b/server/netssl.c index 7557f26624..79c5d3175f 100644 --- a/server/netssl.c +++ b/server/netssl.c @@ -356,6 +356,10 @@ void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg) return; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +#endif /* Note cast to SSLAuthCertificate to prevent warning due to * bad function prototype in NSS. */ @@ -386,6 +390,9 @@ void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg) nss_error("net_starttls / SSL_ConfigSecureServer"); return; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic pop +#endif status = SSL_ResetHandshake(client->ssl, PR_TRUE); if (status != SECSuccess) { From 106e7c6fe7e0c67a7964e254ae8983f4537d8103 Mon Sep 17 00:00:00 2001 From: sapireli <114778791+sapireli@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:48:12 -0400 Subject: [PATCH 1179/1232] @jimklimov my apologies i royally screwed up the pull request with a rebase. I just started a new to have a clean slate scnario. also added the NUT_UNUSED_VARIABLE per your recommendation. tripplite_usb.c Added UPS ID (upsid) Support: The code now includes support for matching and uniquely identifying UPS devices using the UPS ID (upsid). The upsid configuration option has been added, which accepts a regular expression to match the UPS ID string. This was done by adding a new function called match_by_unitid, that reads the upsid from the config file, then reads the upsid from the device, and checks if they match. This function is now passed to the comm_driver matcher on first connect and reconnects. Added the upsid to the upsdrv_makevartable function so it is read and stored from the config file. tripplite_usb.txt Updated Documentation: The driver documentation was updated to reflect the new functionality. The "EXTRA ARGUMENTS" section now includes information about the upsid configuration option, and how to set it. thank you to @jimklimov for pointing me in the right direction and hand holding. Signed-off-by: sapireli <114778791+sapireli@users.noreply.github.com> --- docs/man/tripplite_usb.txt | 18 ++++++++---- docs/nut.dict | 1 + drivers/tripplite_usb.c | 59 +++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/docs/man/tripplite_usb.txt b/docs/man/tripplite_usb.txt index 252697a52c..087a310aa4 100644 --- a/docs/man/tripplite_usb.txt +++ b/docs/man/tripplite_usb.txt @@ -63,6 +63,14 @@ file (or with '-x' on the command line): include::nut_usb_addvars.txt[] +- `-x upsid="12345"` + +Select a specific UPS by its unique UPS ID. The argument is a regular expression +that must match the UPS ID string. This allows for precise identification of UPS +devices when multiple devices of the same make and model are connected. +See below regarding how to read and write the ups id (unit id) using linkman:upsrw[8]. + + [NOTE] .Notes for `tripplite_usb` driver handling of common USB matching settings: ====== @@ -110,7 +118,7 @@ changed at runtime by linkman:upsrw[8]. *ups.id*:: -Some SMARTPRO models feature an ID that can be set and retrieved. +Some SMARTPRO models feature an Unit ID (ups.id) that can be set and retrieved. If your UPS supports this feature, this variable will be listed in the output of linkman:upsrw[8]. @@ -143,10 +151,10 @@ same time, since they have different USB Product ID strings. If you have two SMART1500RM2U units, you would have to find which USB bus and device number each unit is on (via lsusb(8)). -Some of the SMART*2U models have an ID number, but because this ID is not -exposed as a USB string descriptor, there is no easy way to use this ID to -distinguish between multiple UPS units on a single machine. The UPS would need -to be claimed by the driver in order to read this ID. +Some of the SMART*2U models have a configurable Unit ID number, and you can now use the `upsid` +config argument to uniquely specify which UPS a given driver instance should control. +This allows for precise identification of UPS devices when multiple devices are connected. +To retrieve or set the upsid use the linkman:upsrw[8] utility. AUTHORS ------- diff --git a/docs/nut.dict b/docs/nut.dict index d907cce2cb..137962cd7f 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1319,6 +1319,7 @@ UPS's UPSCONN UPSDESC UPSHOST +upsid UPSIMAGEPATH UPSLC UPSOutletSystemOutletDelayBeforeReboot diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 505f69fc9d..0854e28b5d 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -10,6 +10,7 @@ Copyright (C) 2004 Nicholas J. Kain Copyright (C) 2005-2008, 2014 Charles Lepple Copyright (C) 2016 Eaton + Copyright (C) 2023 Eliran Sapir 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 @@ -136,7 +137,7 @@ #include "usb-common.h" #define DRIVER_NAME "Tripp Lite OMNIVS / SMARTPRO driver" -#define DRIVER_VERSION "0.34" +#define DRIVER_VERSION "0.35" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -145,7 +146,8 @@ upsdrv_info_t upsdrv_info = { "Charles Lepple \n" \ "Russell Kroll \n" \ "Rickard E. (Rik) Faith \n" \ - "Nicholas J. Kain ", + "Nicholas J. Kain \n", \ + "Eliran Sapir ", DRV_EXPERIMENTAL, { NULL } }; @@ -282,6 +284,8 @@ static int is_smart_protocol(void) #define MAX_VOLT 13.4 /*!< Max battery voltage (100%) */ #define MIN_VOLT 11.0 /*!< Min battery voltage (10%) */ +#define DEFAULT_UPSID 65535 + static USBDevice_t *hd = NULL; static USBDevice_t curDevice; static USBDeviceMatcher_t *reopen_matcher = NULL; @@ -314,6 +318,49 @@ static long battery_voltage_nominal = 12, static unsigned int offdelay = DEFAULT_OFFDELAY; /* static unsigned int bootdelay = DEFAULT_BOOTDELAY; */ +// Function declaration for send_cmd +static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *reply, size_t reply_len); + +/* Driver matching by ups.id since serial number isn't exposed on some Tripplite models. + Ups.id is the same as Unit Id, and it is a user configurable value between 1-65535. + Default Unit Id is 65535. May be set with upsrw, and it persists after powerloss as well. + To match by ups id, (upsid='your ups id') must be defined inside the ups.conf +*/ +int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen); +int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) +{ + NUT_UNUSED_VARIABLE(udev); + NUT_UNUSED_VARIABLE(hd); + NUT_UNUSED_VARIABLE(rdbuf); + NUT_UNUSED_VARIABLE(rdlen); + char *value = getval("upsid"); + int config_unit_id = 0; + ssize_t ret; + unsigned char u_msg[] = "U"; + unsigned char u_value[9]; + // Read ups id from the ups.conf + if (value != NULL) { + config_unit_id = atoi(value); + } + // Read ups id from the device + if (tl_model != TRIPP_LITE_OMNIVS && tl_model != TRIPP_LITE_SMART_0004) { + /* Unit ID might not be supported by all models: */ + ret = send_cmd(u_msg, sizeof(u_msg), u_value, sizeof(u_value) - 1); + if (ret <= 0) { + upslogx(LOG_INFO, "Unit ID not retrieved (not available on all models)"); + } else { + unit_id = (int)((unsigned)(u_value[1]) << 8) | (unsigned)(u_value[2]); + } + } + + // Check if the ups ids match + if (config_unit_id == unit_id) { + return 1; + } else { + return 0; + } +} + /*!@brief Try to reconnect once. * @return 1 if reconnection was successful. */ @@ -331,7 +378,7 @@ static int reconnect_ups(void) upsdebugx(2, "= device has been disconnected, try to reconnect ="); upsdebugx(2, "=================================================="); - ret = comm_driver->open_dev(&udev, &curDevice, reopen_matcher, NULL); + ret = comm_driver->open_dev(&udev, &curDevice, reopen_matcher, match_by_unitid); if (ret < 1) { upslogx(LOG_INFO, "Reconnecting to UPS failed; will retry later..."); dstate_datastale(); @@ -1551,6 +1598,10 @@ void upsdrv_makevartable(void) MAX_VOLT); addvar(VAR_VALUE, "battery_max", msg); + // allow -x upsid=X + snprintf(msg, sizeof msg, "UPS ID (Unit ID) (default=%d)", DEFAULT_UPSID); + addvar(VAR_VALUE, "upsid", msg); + #if 0 snprintf(msg, sizeof msg, "Set start delay, in seconds (default=%d).", DEFAULT_STARTDELAY); @@ -1598,7 +1649,7 @@ void upsdrv_initups(void) /* Search for the first supported UPS matching the regular * expression */ - r = comm_driver->open_dev(&udev, &curDevice, regex_matcher, NULL); + r = comm_driver->open_dev(&udev, &curDevice, regex_matcher, match_by_unitid); if (r < 1) { fatalx(EXIT_FAILURE, "No matching USB/HID UPS found"); } From 69ffc71ebbbacb851ef41f53139d394b15140f79 Mon Sep 17 00:00:00 2001 From: sapireli <114778791+sapireli@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:00:28 -0400 Subject: [PATCH 1180/1232] @jimklimov my apologies please dont kill me for closing the pull request just saw your typo fix on the old one implemented it here. Signed-off-by: sapireli <114778791+sapireli@users.noreply.github.com> --- drivers/tripplite_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 0854e28b5d..a2f1418bf4 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -146,7 +146,7 @@ upsdrv_info_t upsdrv_info = { "Charles Lepple \n" \ "Russell Kroll \n" \ "Rickard E. (Rik) Faith \n" \ - "Nicholas J. Kain \n", \ + "Nicholas J. Kain \n" \ "Eliran Sapir ", DRV_EXPERIMENTAL, { NULL } From 37752e5939d32b33108469bd64c3fc09b8cbd807 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Oct 2023 00:06:46 +0200 Subject: [PATCH 1181/1232] drivers/tripplite_usb.c: cosmetic fixes (whitespace) Signed-off-by: Jim Klimov --- drivers/tripplite_usb.c | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index a2f1418bf4..f6289c5021 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -318,7 +318,7 @@ static long battery_voltage_nominal = 12, static unsigned int offdelay = DEFAULT_OFFDELAY; /* static unsigned int bootdelay = DEFAULT_BOOTDELAY; */ -// Function declaration for send_cmd +/* Function declaration for send_cmd */ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *reply, size_t reply_len); /* Driver matching by ups.id since serial number isn't exposed on some Tripplite models. @@ -329,36 +329,39 @@ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *rep int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen); int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) { - NUT_UNUSED_VARIABLE(udev); - NUT_UNUSED_VARIABLE(hd); - NUT_UNUSED_VARIABLE(rdbuf); - NUT_UNUSED_VARIABLE(rdlen); char *value = getval("upsid"); int config_unit_id = 0; - ssize_t ret; - unsigned char u_msg[] = "U"; - unsigned char u_value[9]; - // Read ups id from the ups.conf + ssize_t ret; + unsigned char u_msg[] = "U"; + unsigned char u_value[9]; + + NUT_UNUSED_VARIABLE(udev); + NUT_UNUSED_VARIABLE(hd); + NUT_UNUSED_VARIABLE(rdbuf); + NUT_UNUSED_VARIABLE(rdlen); + + /* Read ups id from the ups.conf */ if (value != NULL) { config_unit_id = atoi(value); } - // Read ups id from the device - if (tl_model != TRIPP_LITE_OMNIVS && tl_model != TRIPP_LITE_SMART_0004) { - /* Unit ID might not be supported by all models: */ - ret = send_cmd(u_msg, sizeof(u_msg), u_value, sizeof(u_value) - 1); - if (ret <= 0) { - upslogx(LOG_INFO, "Unit ID not retrieved (not available on all models)"); - } else { - unit_id = (int)((unsigned)(u_value[1]) << 8) | (unsigned)(u_value[2]); - } - } - // Check if the ups ids match - if (config_unit_id == unit_id) { - return 1; - } else { - return 0; - } + /* Read ups id from the device */ + if (tl_model != TRIPP_LITE_OMNIVS && tl_model != TRIPP_LITE_SMART_0004) { + /* Unit ID might not be supported by all models: */ + ret = send_cmd(u_msg, sizeof(u_msg), u_value, sizeof(u_value) - 1); + if (ret <= 0) { + upslogx(LOG_INFO, "Unit ID not retrieved (not available on all models)"); + } else { + unit_id = (int)((unsigned)(u_value[1]) << 8) | (unsigned)(u_value[2]); + } + } + + /* Check if the ups ids match */ + if (config_unit_id == unit_id) { + return 1; + } else { + return 0; + } } /*!@brief Try to reconnect once. From 4809df34a9958cd2a00274f5fdf16d83e212186e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Oct 2023 00:09:14 +0200 Subject: [PATCH 1182/1232] NEWS.adoc: tripplite_usb allows `upsid` setting [#2075] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index b640d8f1d0..e23ae422c6 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -178,6 +178,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - powercom driver should now try harder to refresh data from device [#356] + - tripplite_usb driver now supports configuration of `upsid` to match the + specific device (not all firmware/hardware models support this) [#2075] + - apcupsd-ups: * improvement for `POLL_INTERVAL_MIN` from PR #797 was buggy [#2007] * fix to clean obsoleted readings (if any) AFTER getting new info from an From c9b2a6570f97752ab32961f1fa825cecee2a5523 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Oct 2023 00:15:13 +0200 Subject: [PATCH 1183/1232] drivers/sms_ser.c: use explicit void in function prototypes Signed-off-by: Jim Klimov --- drivers/sms_ser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/sms_ser.c b/drivers/sms_ser.c index 4dd6ef14fe..572a114dac 100644 --- a/drivers/sms_ser.c +++ b/drivers/sms_ser.c @@ -152,7 +152,7 @@ void sms_parse_results(uint8_t *rawvalues, SmsData *results) { results->onbattery = ((byte & (mask << 7)) != 0) ? true : false; } -static int get_ups_nominal() { +static int get_ups_nominal(void) { uint8_t length; ssize_t ret; @@ -184,7 +184,7 @@ static int get_ups_nominal() { return -1; } -static int get_ups_information() { +static int get_ups_information(void) { uint8_t length; ssize_t ret; @@ -216,7 +216,7 @@ static int get_ups_information() { return -1; } -static int get_ups_features() { +static int get_ups_features(void) { uint8_t length; ssize_t ret; From 01363fabfac70b6446574f11bfaa22c9f64583a2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Oct 2023 02:17:03 +0200 Subject: [PATCH 1184/1232] drivers/tripplite_usb.c: avoid varname shadowing Signed-off-by: Jim Klimov --- drivers/tripplite_usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index f6289c5021..f4e2a1560b 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -326,8 +326,8 @@ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *rep Default Unit Id is 65535. May be set with upsrw, and it persists after powerloss as well. To match by ups id, (upsid='your ups id') must be defined inside the ups.conf */ -int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen); -int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) +int match_by_unitid(usb_dev_handle *argudev, USBDevice_t *arghd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen); +int match_by_unitid(usb_dev_handle *argudev, USBDevice_t *arghd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) { char *value = getval("upsid"); int config_unit_id = 0; @@ -335,8 +335,8 @@ int match_by_unitid(usb_dev_handle *udev, USBDevice_t *hd, usb_ctrl_charbuf rdbu unsigned char u_msg[] = "U"; unsigned char u_value[9]; - NUT_UNUSED_VARIABLE(udev); - NUT_UNUSED_VARIABLE(hd); + NUT_UNUSED_VARIABLE(argudev); + NUT_UNUSED_VARIABLE(arghd); NUT_UNUSED_VARIABLE(rdbuf); NUT_UNUSED_VARIABLE(rdlen); From 35630f12dc1a2a3ea81063b01185f20575454395 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 13 Oct 2023 15:28:02 +0200 Subject: [PATCH 1185/1232] NEWS.adoc: sms_ser introduced [#2090] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index b640d8f1d0..7e2773d32f 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -155,6 +155,9 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. - nutdrv_qx and blazer updates: * extended default ranges for max battery voltage when guessing [#1279] + - sms_ser, a driver for SMS Brazil UPS Protocol 1Phase, was introduced. + NOTE: it may later become a subdriver under nutdrv_qx. [#2090] + - usbhid-ups updates: * added support for `subdriver` configuration option, to select the USB HID subdriver for the device manually where automatic match From 31323878864bddfba82e2e87713c692a5acb4eb7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 13 Oct 2023 15:28:12 +0200 Subject: [PATCH 1186/1232] docs/man/sms_ser.txt: update some wording Signed-off-by: Jim Klimov --- docs/man/sms_ser.txt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/man/sms_ser.txt b/docs/man/sms_ser.txt index bc18b87c38..c5676729f1 100644 --- a/docs/man/sms_ser.txt +++ b/docs/man/sms_ser.txt @@ -13,15 +13,22 @@ SYNOPSIS *sms_ser* -a 'UPS_NAME' ['OPTIONS'] -NOTE: This man page only documents the hardware-specific features of the -sms_ser driver. For information about the core driver, see -linkman:nutupsdrv[8] and on doc/sms-brazil-protocol.txt. +NOTE: This man page only documents the hardware-specific features +of the sms_ser driver. For information about the core driver, see +linkman:nutupsdrv[8], and for the technical background check in +doc/sms-brazil-protocol.txt. + +NOTE: Given the proximity of this protocol to Megatec Qx family, +this driver may later become part of `nutdrv_qx` collection. + SUPPORTED HARDWARE ------------------ -sms_ser supports only the sms 1phase SMS Product, get from `monofasico.xml` file. -Other SMS protocols for another products are not supported. +sms_ser supports only the "sms 1phase" SMS Product, as described in +the `monofasico.xml` file delivered with the device. + +Other SMS protocols for their other products are not supported. AUTHOR From 40e41073ce4055a86ddabad363366b5a6410adbc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Oct 2023 15:01:19 +0200 Subject: [PATCH 1187/1232] drivers/usbhid-ups.c: set CAL status before reporting other possibly critical power states [#2104, #2044, fallout of #2055] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index c078354805..806382c510 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1856,6 +1856,15 @@ static void ups_status_set(void) dstate_delinfo("input.transfer.reason"); } + /* Report calibration mode first, because it looks like OFF or OB + * for many implementations (literally, it is a temporary OB state + * managed by the UPS hardware to become OL later... if it guesses + * correctly when to do so), and may cause false alarms for us to + * raise FSD urgently. So we first let upsmon know it is just a drill. + */ + if (ups_status & STATUS(CALIB)) { + status_set("CAL"); /* calibration */ + } if (!(ups_status & STATUS(ONLINE))) { status_set("OB"); /* on battery */ @@ -1907,9 +1916,6 @@ static void ups_status_set(void) if (ups_status & STATUS(OFF)) { status_set("OFF"); /* ups is off */ } - if (ups_status & STATUS(CALIB)) { - status_set("CAL"); /* calibration */ - } } /* find info element definition in info array From e7a3a00826aa018dee397a2639680bb235057926 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Oct 2023 18:39:12 +0200 Subject: [PATCH 1188/1232] clients/upsmon.c et al: introduce OFFDURATION config toggle [#2104] Signed-off-by: Jim Klimov --- NEWS.adoc | 7 ++++- clients/upsmon.c | 56 ++++++++++++++++++++++++++++++++++++-- clients/upsmon.h | 3 ++ conf/upsmon.conf.sample.in | 19 +++++++++++++ docs/man/upsmon.conf.txt | 21 ++++++++++++++ docs/nut.dict | 3 +- 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index d9aba5af42..1820f262fd 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -404,7 +404,12 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. `MONITOR`'ed amount of power sources are considered not being "fed" for the power value calculation purposes. The `BYPASS` state is now treated similarly to `ONBATT`: currently this UPS "feeds" its load, but if later - communications fail, it is considered dead. [#2044] + communications fail, it is considered dead. This may have unintended + consequences for devices (or NUT drivers) that do not report these modes + correctly, e.g. an APC calibration routine seems to start with a few + seconds of "OFF" state, so the reported status is only considered as a + loss of feed if it persists for more than `OFFDURATION` seconds. [#2044, + #2104] - Extended Linux systemd support with optional notifications about daemon state (READY, RELOADING, STOPPING) and watchdog keep-alive messages [#1590] diff --git a/clients/upsmon.c b/clients/upsmon.c index 125086f9be..7afa9ebf3a 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -67,6 +67,23 @@ static unsigned int pollfreq = 5, pollfreqalert = 5; */ static int pollfail_log_throttle_max = -1; + /* We support "administrative OFF" for power devices which can + * be managed to turn off their load while the UPS or ePDU remains + * accessible for monitoring and management. This toggle allows + * to delay propagation of such state into a known loss of a feed + * (possibly triggering FSD on MONITOR'ing clients that are in fact + * still alive - e.g. with multiple power sources), because when + * some devices begin battery calibration, they report "OFF" for + * a few seconds and only then they report "CAL" after switching + * all the power relays (causing false-positives for FSD trigger). + * A negative value means to disable decreasing the power-source + * counter in such cases, and a zero makes the effect immediate. + * NOTE: so far we support the device reporting an "OFF" state + * which usually means completely un-powering the load; TODO was + * logged for adding similar support for just some outlets/groups. + */ +static int offdurationtime = 30; + /* secondary hosts are given 15 sec by default to logout from upsd */ static int hostsync = 15; @@ -569,14 +586,42 @@ static void ups_is_gone(utype_t *ups) static void ups_is_off(utype_t *ups) { - if (flag_isset(ups->status, ST_OFF)) { /* no change */ + time_t now; + + time(&now); + + if (flag_isset(ups->status, ST_OFF)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); + if (ups->offsince < 1) { + /* Should not happen, but just in case */ + ups->offsince = now; + } else { + if (offdurationtime > 0 && (now - ups->offsince) > offdurationtime) { + /* This should be a rare but urgent situation + * that warrants an extra notification? */ + upslogx(LOG_WARNING, "%s: %s is in state OFF for %d sec, " + "assuming the line is not fed " + "(if it is calibrating etc., check " + "the upsmon 'OFFDURATION' option)", + __func__, ups->sys, (int)(now - ups->offsince)); + ups->linestate = 0; + } + } return; } sleepval = pollfreqalert; /* bump up polling frequency */ - ups->linestate = 0; + ups->offsince = now; + if (offdurationtime == 0) { + /* This should be a rare but urgent situation + * that warrants an extra notification? */ + upslogx(LOG_WARNING, "%s: %s is in state OFF, assuming the line is not fed (if it is calibrating etc., check the upsmon 'OFFDURATION' option)", __func__, ups->sys); + ups->linestate = 0; + } else + if (offdurationtime < 0) { + upsdebugx(1, "%s: %s is in state OFF, but we are not assuming the line is not fed (due to upsmon 'OFFDURATION' option)", __func__, ups->sys); + } upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); @@ -590,6 +635,7 @@ static void ups_is_off(utype_t *ups) static void ups_is_notoff(utype_t *ups) { /* Called when OFF is NOT among known states */ + ups->offsince = 0; if (flag_isset(ups->status, ST_OFF)) { /* actual change */ do_notify(ups, NOTIFY_NOTOFF); clearflag(&ups->status, ST_OFF); @@ -1538,6 +1584,12 @@ static int parse_conf_arg(size_t numargs, char **arg) return 1; } + /* OFFDURATION */ + if (!strcmp(arg[0], "OFFDURATION")) { + offdurationtime = atoi(arg[1]); + return 1; + } + /* HOSTSYNC */ if (!strcmp(arg[0], "HOSTSYNC")) { hostsync = atoi(arg[1]); diff --git a/clients/upsmon.h b/clients/upsmon.h index c1ed5ffd08..3caba49b3a 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -73,6 +73,9 @@ typedef struct { time_t lastnoncrit; /* time of last non-crit poll */ time_t lastrbwarn; /* time of last REPLBATT warning*/ time_t lastncwarn; /* time of last NOCOMM warning */ + + time_t offsince; /* time of recent entry into OFF state */ + void *next; } utype_t; diff --git a/conf/upsmon.conf.sample.in b/conf/upsmon.conf.sample.in index 0bb4c501a9..e26b487c91 100644 --- a/conf/upsmon.conf.sample.in +++ b/conf/upsmon.conf.sample.in @@ -331,6 +331,25 @@ POWERDOWNFLAG "@POWERDOWNFLAG@" # # If you use IGNORE, don't use any other flags on the same line. +# -------------------------------------------------------------------------- +# OFFDURATION - put "OFF" state into effect if it persists for this many seconds +# +# NUT supports an "administrative OFF" for power devices which can be managed to +# turn off their application workload, while the UPS or ePDU remains accessible +# for monitoring and management. This toggle allows to delay propagation of such +# state into a known loss of a feed (possibly triggering FSD on `upsmon` clients +# which `MONITOR` the device and are in fact still alive -- e.g. with multiple +# power sources or because they as the load are not really turned off), because +# when some devices begin battery calibration, they report "OFF" for a few seconds +# and only then they might report "CAL" after switching all the power relays -- +# thus causing false-positives for `upsmon` FSD trigger. +# +# A negative value means to disable decreasing the counter of working power +# supplies in such cases, and a zero makes the effect of detected "OFF" state +# immediate. Built-in default value is 30 (seconds). + +OFFDURATION 30 + # -------------------------------------------------------------------------- # RBWARNTIME - replace battery warning time in seconds # diff --git a/docs/man/upsmon.conf.txt b/docs/man/upsmon.conf.txt index 0997c9ea0e..faf3135c9c 100644 --- a/docs/man/upsmon.conf.txt +++ b/docs/man/upsmon.conf.txt @@ -318,6 +318,27 @@ Refer to the section: [[UPS_shutdown]] "Configuring automatic shutdowns for low battery events", or refer to the online version. +*OFFDURATION* 'seconds':: + +NUT supports an "administrative OFF" for power devices which can be managed to +turn off their application workload, while the UPS or ePDU remains accessible +for monitoring and management. This toggle allows to delay propagation of such +state into a known loss of a feed (possibly triggering FSD on `upsmon` clients +which `MONITOR` the device and are in fact still alive -- e.g. with multiple +power sources or because they as the load are not really turned off), because +when some devices begin battery calibration, they report "OFF" for a few seconds +and only then they might report "CAL" after switching all the power relays -- +thus causing false-positives for `upsmon` FSD trigger. ++ +A negative value means to disable decreasing the counter of working power +supplies in such cases, and a zero makes the effect of detected "OFF" state +immediate. Built-in default value is 30 (seconds), to put an "OFF" state into +effect (decrease known-fed supplies count) if it persists for this many seconds. ++ +NOTE: so far we support the device reporting an "OFF" state which usually +means completely un-powering the load; a bug-tracker issue was logged to +design similar support for just some manageable outlets or outlet groups. + *RBWARNTIME* 'seconds':: When a UPS says that it needs to have its battery replaced, upsmon will diff --git a/docs/nut.dict b/docs/nut.dict index 176b9fbcda..745fd4636f 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3246 utf-8 +personal_ws-1.1 en 3247 utf-8 AAS ABI ACFAIL @@ -818,6 +818,7 @@ OC ODH OEM OEM'ed +OFFDURATION OID OIDs OLHVT From be169db3a3b124490f617157d07b390d7015e160 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Oct 2023 18:45:33 +0200 Subject: [PATCH 1189/1232] clients/upsmon.c: reword a message for critically lost primary UPS Signed-off-by: Jim Klimov --- clients/upsmon.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 7afa9ebf3a..e0ca44c032 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1070,8 +1070,9 @@ static int is_ups_critical(utype_t *ups) /* give the primary up to HOSTSYNC seconds before shutting down */ if ((now - ups->lastnoncrit) > hostsync) { - upslogx(LOG_WARNING, "Giving up on the primary for UPS [%s]", - ups->sys); + upslogx(LOG_WARNING, "Giving up on the primary for UPS [%s] " + "after %d sec since last comms", + ups->sys, (int)(now - ups->lastnoncrit)); return 1; } From 2647f026f7f0c856926da67cec845a09bed2a5d1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Oct 2023 18:46:54 +0200 Subject: [PATCH 1190/1232] clients/upsmon.c: revise is_ups_critical() with OFF, BYPASS and CAL considerations [#2104] Signed-off-by: Jim Klimov --- clients/upsmon.c | 51 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index e0ca44c032..45d99a8ddc 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1038,9 +1038,52 @@ static int is_ups_critical(utype_t *ups) if (flag_isset(ups->status, ST_FSD)) return 1; + if (ups->commstate == 0) { + if (flag_isset(ups->status, ST_CAL)) { + upslogx(LOG_WARNING, + "UPS [%s] was last known to be calibrating " + "and currently is not communicating, assuming dead", + ups->sys); + return 1; + } + + if (flag_isset(ups->status, ST_BYPASS)) { + upslogx(LOG_WARNING, + "UPS [%s] was last known to be on BYPASS " + "and currently is not communicating, assuming dead", + ups->sys); + return 1; + } + + if (flag_isset(ups->status, ST_OFF) && offdurationtime >= 0) { + upslogx(LOG_WARNING, + "UPS [%s] was last known to be (administratively) OFF " + "and currently is not communicating, assuming dead", + ups->sys); + return 1; + } + + if (ups->linestate == 0) { + upslogx(LOG_WARNING, + "UPS [%s] was last known to be not fully online " + "and currently is not communicating, assuming dead", + ups->sys); + return 1; + } + } + + /* administratively OFF (long enough, see OFFDURATION) */ + if (flag_isset(ups->status, ST_OFF) && offdurationtime >= 0 && ups->linestate == 0) { + upslogx(LOG_WARNING, + "UPS [%s] is reported as (administratively) OFF", + ups->sys); + return 1; + } + /* not OB or not LB = not critical yet */ - if ((!flag_isset(ups->status, ST_ONBATT)) || - (!flag_isset(ups->status, ST_LOWBATT))) + if ((!flag_isset(ups->status, ST_ONBATT)) + || (!flag_isset(ups->status, ST_LOWBATT)) + ) return 0; /* must be OB+LB now */ @@ -1102,10 +1145,10 @@ static void recalc(void) * this means a UPS we've never heard from is assumed OL * * whether this is really the best thing to do is undecided */ - /* crit = (FSD) || (OB & LB) > HOSTSYNC seconds */ + /* crit = (FSD) || (OB & LB) > HOSTSYNC seconds || (OFF || BYPASS) && nocomms */ if (is_ups_critical(ups)) upsdebugx(1, "Critical UPS: %s", ups->sys); - else if (!flag_isset(ups->status, ST_OFF)) + else val_ol += ups->pv; ups = ups->next; From c39c895c5b3e45f19847bfe68cd219a3a817e6b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 15 Oct 2023 22:37:18 +0200 Subject: [PATCH 1191/1232] Update NEWS.adoc: clarify wording Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 1820f262fd..7a84495342 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -406,8 +406,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. similarly to `ONBATT`: currently this UPS "feeds" its load, but if later communications fail, it is considered dead. This may have unintended consequences for devices (or NUT drivers) that do not report these modes - correctly, e.g. an APC calibration routine seems to start with a few - seconds of "OFF" state, so the reported status is only considered as a + correctly (e.g. an APC calibration routine seems to start with a few + seconds of "OFF" state), so the reported status is only considered as a loss of feed if it persists for more than `OFFDURATION` seconds. [#2044, #2104] From 7ac1da177245b836c21ff8422dc4a58df65fda79 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 09:50:19 +0200 Subject: [PATCH 1192/1232] drivers/usbhid-ups.c, docs/man/usbhid-ups.txt, NEWS.adoc: introduce onlinedischarge_calibration config option [#2104] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ docs/man/usbhid-ups.txt | 10 ++++++++++ drivers/usbhid-ups.c | 32 ++++++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 7a84495342..fb6ba84db1 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -178,6 +178,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * powercom-hid subdriver: fixed `UPS.Battery.ManufacturerDate` to map to `battery.mfr.date` (not `battery.date` which is the maintenance replacement date) [#1644] + * added `onlinedischarge_calibration` option for UPSes that report + `OL+DISCHRG` when they are in calibration mode [#2104] - powercom driver should now try harder to refresh data from device [#356] diff --git a/docs/man/usbhid-ups.txt b/docs/man/usbhid-ups.txt index 0a916fbc4f..c54e2bfa76 100644 --- a/docs/man/usbhid-ups.txt +++ b/docs/man/usbhid-ups.txt @@ -116,6 +116,16 @@ For most devices this combination means calibration or similar maintenance; however some UPS models (e.g. CyberPower UT series) emit `OL+DISCHRG` when wall power is lost -- and need this option to handle shutdowns. +*onlinedischarge_calibration*:: +If this flag is set, the driver will treat `OL+DISCHRG` status as calibration. +Some UPS models (e.g. APC were seen to do so) report `OL+DISCHRG` when they +are in calibration mode. This usually happens after a few seconds reporting +an `OFF` state as well, while the hardware is switching to on-battery mode. ++ +NOTE: If it takes so long on your device that a shutdown gets issued, you may +want to look at `upsmon` option `OFFDURATION` used to filter out temporary +values of "administrative OFF" as not a loss of a feed for the powered load. + *disable_fix_report_desc*:: Set to disable fix-ups for broken USB encoding, etc. which we apply by default on certain models (vendors/products) which were reported as not following the diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 806382c510..585b618982 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -148,6 +148,13 @@ hid_dev_handle_t udev = HID_DEV_HANDLE_CLOSED; */ static int onlinedischarge = 0; +/** + * Some UPS models (e.g. APC were seen to do so) report OL & DISCHRG when they + * are in calibration mode. This usually happens after a few seconds reporting + * an "OFF" state as well, while the hardware is switching to on-battery mode. + */ +static int onlinedischarge_calibration = 0; + /* support functions */ static hid_info_t *find_nut_info(const char *varname); static hid_info_t *find_hid_info(const HIDData_t *hiddata); @@ -939,6 +946,9 @@ void upsdrv_makevartable(void) addvar(VAR_FLAG, "onlinedischarge", "Set to treat discharging while online as being offline"); + addvar(VAR_FLAG, "onlinedischarge_calibration", + "Set to treat discharging while online as doing calibration"); + addvar(VAR_FLAG, "disable_fix_report_desc", "Set to disable fix-ups for broken USB encoding, etc. which we apply by default on certain vendors/products"); @@ -1249,6 +1259,10 @@ void upsdrv_initups(void) onlinedischarge = 1; } + if (testvar("onlinedischarge_calibration")) { + onlinedischarge_calibration = 1; + } + if (testvar("disable_fix_report_desc")) { disable_fix_report_desc = 1; } @@ -1869,24 +1883,34 @@ static void ups_status_set(void) if (!(ups_status & STATUS(ONLINE))) { status_set("OB"); /* on battery */ } else if ((ups_status & STATUS(DISCHRG))) { - /* if online */ + /* if online but discharging */ + if (onlinedischarge_calibration) { + /* if we treat OL+DISCHRG as calibrating */ + status_set("CAL"); /* calibration */ + } + if (onlinedischarge) { /* if we treat OL+DISCHRG as being offline */ status_set("OB"); /* on battery */ - } else { + } + + if (!onlinedischarge && !onlinedischarge_calibration) { if (!(ups_status & STATUS(CALIB))) { /* if in OL+DISCHRG unknowingly, warn user */ upslogx(LOG_WARNING, "%s: seems that UPS [%s] is in OL+DISCHRG state now. " - "Is it calibrating or do you perhaps want to set 'onlinedischarge' option? " - "Some UPS models (e.g. CyberPower UT series) emit OL+DISCHRG when offline.", + "Is it calibrating (perhaps you want to set 'onlinedischarge_calibration' option)? " + "Note that some UPS models (e.g. CyberPower UT series) emit OL+DISCHRG when " + "in fact offline/on-battery (perhaps you want to set 'onlinedischarge' option).", __func__, upsname); } /* if we're calibrating */ status_set("OL"); /* on line */ } } else if ((ups_status & STATUS(ONLINE))) { + /* if simply online */ status_set("OL"); } + if ((ups_status & STATUS(DISCHRG)) && !(ups_status & STATUS(DEPLETED))) { status_set("DISCHRG"); /* discharging */ From a864aa71ded4101086a9e33265e8fe60a30f7ce9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 11:07:10 +0200 Subject: [PATCH 1193/1232] m4/ax_run_or_link_ifelse.m4: extend with options to customize CFLAGS and CXXFLAGS [#2109] Signed-off-by: Jim Klimov --- m4/ax_run_or_link_ifelse.m4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/m4/ax_run_or_link_ifelse.m4 b/m4/ax_run_or_link_ifelse.m4 index 994994b015..419eb1d59a 100644 --- a/m4/ax_run_or_link_ifelse.m4 +++ b/m4/ax_run_or_link_ifelse.m4 @@ -3,6 +3,10 @@ dnl but it provides the fourth argument to customize the handling. dnl In our case, we would fall back to trying just to link then - dnl the result would not be as relevant regarding run-time behavior dnl of the code, but at least we would know that API and ABI are ok. +dnl Here the fourth and fifth arguments can be used to pass custom +dnl CFLAGS and CXXFLAGS options (e.g. warnings to cover or ignore), +dnl respectively. For the test to succeed, the build/link must pass +dnl without warnings. dnl Per original /usr/share/autoconf/autoconf/general.m4 which makes dnl a similar wrapper: @@ -14,8 +18,8 @@ AC_DEFUN([AX_RUN_OR_LINK_IFELSE], [ myCFLAGS="$CFLAGS" myCXXFLAGS="$CXXFLAGS" - CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration" - CXXFLAGS="$myCXXFLAGS -Werror -Werror=implicit-function-declaration" + CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration $4" + CXXFLAGS="$myCXXFLAGS -Werror -Werror=implicit-function-declaration $5" AC_RUN_IFELSE([$1], [$2], [$3], [ AC_MSG_WARN([Current build is a cross-build, so not running test binaries, just linking them]) From 35c4001705e2966becb29f87c8edad5fe98c5c7f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 11:25:34 +0200 Subject: [PATCH 1194/1232] configure.ac: fix logged output of inet_pton() test Signed-off-by: Jim Klimov --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 66821dde42..14e7ca32a9 100644 --- a/configure.ac +++ b/configure.ac @@ -1205,8 +1205,8 @@ AC_CACHE_CHECK([for inet_pton() with IPv4 and IPv6 support], [[/* int inet_pton(int af, const char *src, char *dst); */ struct in_addr ipv4; struct in6_addr ipv6; -printf("%i", inet_pton(AF_INET, "1.2.3.4", &ipv4)); -printf("%i", inet_pton(AF_INET6, "::1", &ipv6)) +printf("%i ", inet_pton(AF_INET, "1.2.3.4", &ipv4)); +printf("%i ", inet_pton(AF_INET6, "::1", &ipv6)) /* autoconf adds ";return 0;" */ ]])], [ac_cv_func_inet_pton=yes], [ac_cv_func_inet_pton=no] From aae6f44b176be199ecc9dd2e144a9cbf9a7460f1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 11:26:53 +0200 Subject: [PATCH 1195/1232] m4/ax_c_pragmas.m4: extend AX_C_PRINTF_STRING_NULL with use of AX_RUN_OR_LINK_IFELSE option to ignore certain warnings [#2109] Signed-off-by: Jim Klimov --- m4/ax_c_pragmas.m4 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index 070d82beee..ee7033a67a 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -967,6 +967,13 @@ if test -z "${nut_have_ax_c_printf_string_null_seen}"; then nut_have_ax_c_printf_string_null_seen="yes" AC_REQUIRE([AX_RUN_OR_LINK_IFELSE])dnl + dnl Here we do not care if the compiler formally complains about + dnl undefined behavior of printf("%s", NULL) as long as it works + dnl in practice (compiler or libc implement a sane fallback): + myWARN_CFLAGS="" + AS_IF([test "${GCC}" = "yes" || test "${CLANGCC}" = "yes"], + [myWARN_CFLAGS="-Wno-format-truncation -Wno-format-overflow"]) + dnl ### To be sure, bolt the language AC_LANG_PUSH([C]) @@ -979,6 +986,9 @@ if test -z "${nut_have_ax_c_printf_string_null_seen}"; then ], [[ char buf[128]; char *s = NULL; +/* The following line may issue pedantic static analysis warnings (ignored); + * it may also crash (segfault) during a run on some systems - hence the test. + */ int res = snprintf(buf, sizeof(buf), "%s", s); buf[sizeof(buf)-1] = '\0'; if (res < 0) { @@ -997,9 +1007,11 @@ fprintf(stderr, "SUCCESS: RETURNED a string that contains something like 'null' return 0; ]])], [ax_cv__printf_string_null=yes], - [ax_cv__printf_string_null=no] + [ax_cv__printf_string_null=no], + [${myWARN_CFLAGS}] )] ) + unset myWARN_CFLAGS AS_IF([test "$ax_cv__printf_string_null" = "yes"],[ AC_DEFINE([HAVE_PRINTF_STRING_NULL], 1, [define if your libc can printf("%s", NULL) sanely]) From f3b11a65866313b54405f058ea292388820e8713 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 11:51:24 +0200 Subject: [PATCH 1196/1232] m4/ax_c_pragmas.m4, configure.ac: merge two tests for printf("%s", NULL) [#2109] Signed-off-by: Jim Klimov --- configure.ac | 22 ---------------------- m4/ax_c_pragmas.m4 | 29 +++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index 14e7ca32a9..aee139e079 100644 --- a/configure.ac +++ b/configure.ac @@ -1024,28 +1024,6 @@ AC_CHECK_FUNCS(vsnprintf snprintf, [], [ AC_TYPE_LONG_LONG_INT ]) -AC_MSG_CHECKING([whether printf allows null string args]) -AC_LANG_PUSH([C]) -dnl The following code crashes on some libc implementations (e.g. Solaris 8) -dnl TODO: We may need to update NUT codebase to use NUT_STRARG() macro more -dnl often and consistently, or find a way to tweak upsdebugx() etc. varargs -AX_RUN_OR_LINK_IFELSE([AC_LANG_PROGRAM( - [#include ], - [printf("%s", NULL)] -)], - [ - AC_MSG_RESULT([ok]) - AM_CONDITIONAL([REQUIRE_NUT_STRARG], [false]) - ], - [AC_MSG_RESULT([no]) - AC_DEFINE([REQUIRE_NUT_STRARG], [1], - [Define to 1 if your libc requires workarounds to print NULL values.]) - AC_MSG_WARN([Your C library requires workarounds to print NULL values; if something crashes with a segmentation fault (especially with verbose debug) - that may be why]) - AM_CONDITIONAL([REQUIRE_NUT_STRARG], [true]) - ] -) -AC_LANG_POP([C]) - AC_REPLACE_FUNCS(setenv strerror atexit) diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index ee7033a67a..c303571635 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -963,6 +963,10 @@ fi ]) AC_DEFUN([AX_C_PRINTF_STRING_NULL], [ +dnl The following code crashes on some libc implementations (e.g. Solaris 8) +dnl TODO: We may need to update NUT codebase to use NUT_STRARG() macro more +dnl often and consistently, or find a way to tweak upsdebugx() etc. varargs. + if test -z "${nut_have_ax_c_printf_string_null_seen}"; then nut_have_ax_c_printf_string_null_seen="yes" AC_REQUIRE([AX_RUN_OR_LINK_IFELSE])dnl @@ -992,22 +996,35 @@ char *s = NULL; int res = snprintf(buf, sizeof(buf), "%s", s); buf[sizeof(buf)-1] = '\0'; if (res < 0) { - fprintf(stderr, "FAILED to snprintf() a NULL string argument\n"); + fprintf(stderr, "FAILED to snprintf() a variable NULL string argument\n"); return 1; } if (buf[0] == '\0') { - fprintf(stderr, "RETURNED empty string from snprintf() with a NULL string argument\n"); + fprintf(stderr, "RETURNED empty string from snprintf() with a variable NULL string argument\n"); return 0; } if (strstr(buf, "null") == NULL) { - fprintf(stderr, "RETURNED some string from snprintf() with a NULL string argument: '%s'\n", buf); + fprintf(stderr, "RETURNED some string from snprintf() with a variable NULL string argument: '%s'\n", buf); return 0; } -fprintf(stderr, "SUCCESS: RETURNED a string that contains something like 'null' from snprintf() with a NULL string argument: '%s'\n", buf); +fprintf(stderr, "SUCCESS: RETURNED a string that contains something like 'null' from snprintf() with a variable NULL string argument: '%s'\n", buf); + +res = printf("%s", NULL); +if (res < 0) { + fprintf(stderr, "FAILED to printf() an explicit NULL string argument (to stdout)\n"); + return 1; +} return 0; ]])], - [ax_cv__printf_string_null=yes], - [ax_cv__printf_string_null=no], + [ax_cv__printf_string_null=yes + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [false]) + ], + [ax_cv__printf_string_null=no + AC_DEFINE([REQUIRE_NUT_STRARG], [1], + [Define to 1 if your libc requires workarounds to print NULL values.]) + AC_MSG_WARN([Your C library requires workarounds to print NULL values; if something crashes with a segmentation fault (especially during verbose debug) - that may be why]) + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [true]) + ], [${myWARN_CFLAGS}] )] ) From 304d41eac4610dcc60aeeec4e21ee2bc1cac3d9c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 14:41:14 +0200 Subject: [PATCH 1197/1232] Refactor uses of HAVE_PRINTF_STRING_NULL vs. REQUIRE_NUT_STRARG for printf("%s", NULL) support [#2109] Signed-off-by: Jim Klimov --- include/str.h | 3 ++- m4/ax_c_pragmas.m4 | 14 ++++++++------ tests/Makefile.am | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/str.h b/include/str.h index 8654fb98c2..d7aac249f6 100644 --- a/include/str.h +++ b/include/str.h @@ -31,9 +31,10 @@ extern "C" { /* Some compilers and/or C libraries do not handle printf("%s", NULL) correctly */ #ifndef NUT_STRARG -# ifdef HAVE_PRINTF_STRING_NULL +# if (defined REQUIRE_NUT_STRARG) && (REQUIRE_NUT_STRARG == 0) # define NUT_STRARG(x) x # else +/* Is required, or not defined => err on safe side */ # define NUT_STRARG(x) (x?x:"(null)") # endif #endif diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index c303571635..09e5ec0763 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -1017,13 +1017,8 @@ if (res < 0) { return 0; ]])], [ax_cv__printf_string_null=yes - AM_CONDITIONAL([REQUIRE_NUT_STRARG], [false]) ], [ax_cv__printf_string_null=no - AC_DEFINE([REQUIRE_NUT_STRARG], [1], - [Define to 1 if your libc requires workarounds to print NULL values.]) - AC_MSG_WARN([Your C library requires workarounds to print NULL values; if something crashes with a segmentation fault (especially during verbose debug) - that may be why]) - AM_CONDITIONAL([REQUIRE_NUT_STRARG], [true]) ], [${myWARN_CFLAGS}] )] @@ -1031,7 +1026,14 @@ return 0; unset myWARN_CFLAGS AS_IF([test "$ax_cv__printf_string_null" = "yes"],[ - AC_DEFINE([HAVE_PRINTF_STRING_NULL], 1, [define if your libc can printf("%s", NULL) sanely]) + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [false]) + AC_DEFINE([REQUIRE_NUT_STRARG], [0], + [Define to 0 if your libc can printf("%s", NULL) sanely, or to 1 if your libc requires workarounds to print NULL values.]) + ],[ + AM_CONDITIONAL([REQUIRE_NUT_STRARG], [true]) + AC_DEFINE([REQUIRE_NUT_STRARG], [1], + [Define to 0 if your libc can printf("%s", NULL) sanely, or to 1 if your libc requires workarounds to print NULL values.]) + AC_MSG_WARN([Your C library requires workarounds to print NULL values; if something crashes with a segmentation fault (especially during verbose debug) - that may be why]) ]) AC_LANG_POP([C]) diff --git a/tests/Makefile.am b/tests/Makefile.am index da1c03e4bf..b0e79625e7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,7 +30,7 @@ nutlogtest-nofail.sh: nutlogtest$(EXEEXT) @echo '#!/bin/sh' > $@ @echo 'echo "WARNING: Your C library requires workarounds to print NULL values!" >&2' >> $@ @echo 'echo "If nutlogtest below, or generally some NUT program, crashes with" >&2' >> $@ - @echo 'echo "a segmentation fault (especially with verbose debug) - that may be why" >&2' >> $@ + @echo 'echo "a segmentation fault (especially during verbose debug) - that may be why" >&2' >> $@ @echo 'SCRIPT_DIR="`dirname "$$0"`"' >> $@ @echo '"$${SCRIPT_DIR}/nutlogtest" "$$@" || echo "nutlogtest FAILED but it was expected"' >> $@ @chmod +x $@ From 1a7c3a7c44625cd1a974f844707ff0eb56b188e3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 14:42:53 +0200 Subject: [PATCH 1198/1232] m4/ax_run_or_link_ifelse.m4: C++ does not support -Werror=implicit-function-declaration [#2109, #2096 fallout] Signed-off-by: Jim Klimov --- m4/ax_run_or_link_ifelse.m4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/m4/ax_run_or_link_ifelse.m4 b/m4/ax_run_or_link_ifelse.m4 index 419eb1d59a..3714e9e43a 100644 --- a/m4/ax_run_or_link_ifelse.m4 +++ b/m4/ax_run_or_link_ifelse.m4 @@ -19,7 +19,8 @@ AC_DEFUN([AX_RUN_OR_LINK_IFELSE], myCFLAGS="$CFLAGS" myCXXFLAGS="$CXXFLAGS" CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration $4" - CXXFLAGS="$myCXXFLAGS -Werror -Werror=implicit-function-declaration $5" + dnl # cc1plus: error: '-Werror=' argument '-Werror=implicit-function-declaration' is not valid for C++ [-Werror] + CXXFLAGS="$myCXXFLAGS -Werror $5" AC_RUN_IFELSE([$1], [$2], [$3], [ AC_MSG_WARN([Current build is a cross-build, so not running test binaries, just linking them]) From 741832b64fd1c870086264f4b30d6be4f1f72005 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 14:57:26 +0200 Subject: [PATCH 1199/1232] m4/ax_run_or_link_ifelse.m4: revise to only impose gcc/clang warning option requirements into compilers that identify as GCC or CLANG [#2096 fallout] Signed-off-by: Jim Klimov --- m4/ax_run_or_link_ifelse.m4 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/m4/ax_run_or_link_ifelse.m4 b/m4/ax_run_or_link_ifelse.m4 index 3714e9e43a..0a54cbc419 100644 --- a/m4/ax_run_or_link_ifelse.m4 +++ b/m4/ax_run_or_link_ifelse.m4 @@ -18,9 +18,16 @@ AC_DEFUN([AX_RUN_OR_LINK_IFELSE], [ myCFLAGS="$CFLAGS" myCXXFLAGS="$CXXFLAGS" - CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration $4" - dnl # cc1plus: error: '-Werror=' argument '-Werror=implicit-function-declaration' is not valid for C++ [-Werror] - CXXFLAGS="$myCXXFLAGS -Werror $5" + AS_IF([test "${GCC}" = "yes" || test "${CLANGCC}" = "yes"], [ + CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration $4" + dnl # cc1plus: error: '-Werror=' argument '-Werror=implicit-function-declaration' is not valid for C++ [-Werror] + CXXFLAGS="$myCXXFLAGS -Werror $5" + ], [ + dnl # Don't know what to complain about for unknown compilers + dnl # FIXME: Presume here they have at least a "-Werror" option + CFLAGS="$myCFLAGS -Werror $4" + CXXFLAGS="$myCXXFLAGS -Werror $5" + ]) AC_RUN_IFELSE([$1], [$2], [$3], [ AC_MSG_WARN([Current build is a cross-build, so not running test binaries, just linking them]) From d4df70cfe64400486698f915037a936b43475e0c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 16:32:42 +0200 Subject: [PATCH 1200/1232] data/cmdvartab: define descriptions for recently added commands and variables [#2112] Signed-off-by: Jim Klimov --- data/cmdvartab | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/data/cmdvartab b/data/cmdvartab index 5f322c6037..9a1d9ab3a9 100644 --- a/data/cmdvartab +++ b/data/cmdvartab @@ -175,20 +175,29 @@ VARDESC outlet.2.autoswitch.charge.low "Remaining battery level to power off thi VARDESC outlet.2.delay.shutdown "Interval to wait before shutting down this outlet (seconds)" VARDESC outlet.2.delay.start "Interval to wait before restarting this outlet (seconds)" +VARDESC device.part "Device Part Number" + +VARDESC server.info "Server information" +VARDESC server.version "Server version" + VARDESC driver.name "Driver name" +VARDESC driver.debug "Current debug verbosity level of the driver program" +# Note: normally a `drivername -k` call is used during shutdowns, +# and at that time the daemon instance of the driver must be stopped: +VARDESC driver.flag.allow_killpower "Safety flip-switch to allow the driver daemon to send UPS shutdown command (accessible via driver.killpower)" VARDESC driver.version "Driver version - NUT release" VARDESC driver.version.internal "Internal driver version" VARDESC driver.version.usb "USB library version" -VARDESC device.part "Device Part Number" - # FIXME: driver.parameter and driver.flag can have many possible members # # VARDESC driver.parameter.[[:alpha:]]+ "Driver parameter: " # VARDESC driver.flag.[[:alpha:]]+ "Driver flag: " -VARDESC server.info "Server information" -VARDESC server.version "Server version" +CMDDESC driver.killpower "Tell the driver daemon to initiate UPS shutdown; should be unlocked with driver.flag.allow_killpower option or variable setting" +CMDDESC driver.reload "Reload running driver configuration from the file system (only works for changes in some options)" +CMDDESC driver.reload-or-error "Reload running driver configuration from the file system (only works for changes in some options); return an error if something changed and could not be applied live (so the caller can restart it with new options)" +CMDDESC driver.reload-or-exit "Reload running driver configuration from the file system (only works for changes in some options); exit the running driver if something changed and could not be applied live (so service management framework can restart it with new options)" CMDDESC load.off "Turn off the load immediately" CMDDESC load.on "Turn on the load immediately" From 3dbe9dd3a938abafc9cda8d8221ff59b0319854b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 17:22:27 +0200 Subject: [PATCH 1201/1232] clients/upsmon.{c,h}: untie OFF/BYPASS states from ONLINE/ONBATT and linestate attr [#2108] Signed-off-by: Jim Klimov --- clients/upsmon.c | 24 +++++++++++------------- clients/upsmon.h | 4 ++++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 45d99a8ddc..6fa0117db7 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -604,7 +604,7 @@ static void ups_is_off(utype_t *ups) "(if it is calibrating etc., check " "the upsmon 'OFFDURATION' option)", __func__, ups->sys, (int)(now - ups->offsince)); - ups->linestate = 0; + ups->offstate = 1; } } return; @@ -617,7 +617,7 @@ static void ups_is_off(utype_t *ups) /* This should be a rare but urgent situation * that warrants an extra notification? */ upslogx(LOG_WARNING, "%s: %s is in state OFF, assuming the line is not fed (if it is calibrating etc., check the upsmon 'OFFDURATION' option)", __func__, ups->sys); - ups->linestate = 0; + ups->offstate = 1; } else if (offdurationtime < 0) { upsdebugx(1, "%s: %s is in state OFF, but we are not assuming the line is not fed (due to upsmon 'OFFDURATION' option)", __func__, ups->sys); @@ -626,23 +626,21 @@ static void ups_is_off(utype_t *ups) upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* must have changed from !OFF to OFF, so notify */ - do_notify(ups, NOTIFY_OFF); setflag(&ups->status, ST_OFF); - clearflag(&ups->status, ST_ONLINE); } static void ups_is_notoff(utype_t *ups) { /* Called when OFF is NOT among known states */ ups->offsince = 0; + ups->offstate = 0; if (flag_isset(ups->status, ST_OFF)) { /* actual change */ do_notify(ups, NOTIFY_NOTOFF); clearflag(&ups->status, ST_OFF); if (!flag_isset(ups->status, ST_ONBATT)) { sleepval = pollfreq; - ups->linestate = 1; setflag(&ups->status, ST_ONLINE); } } @@ -657,7 +655,7 @@ static void ups_is_bypass(utype_t *ups) sleepval = pollfreqalert; /* bump up polling frequency */ - ups->linestate = 0; /* if we lose comms, consider it AWOL */ + ups->bypassstate = 1; /* if we lose comms, consider it AWOL */ upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); @@ -665,19 +663,18 @@ static void ups_is_bypass(utype_t *ups) do_notify(ups, NOTIFY_BYPASS); setflag(&ups->status, ST_BYPASS); - clearflag(&ups->status, ST_ONLINE); } static void ups_is_notbypass(utype_t *ups) { /* Called when BYPASS is NOT among known states */ + ups->bypassstate = 0; if (flag_isset(ups->status, ST_BYPASS)) { /* actual change */ do_notify(ups, NOTIFY_NOTBYPASS); clearflag(&ups->status, ST_BYPASS); if (!flag_isset(ups->status, ST_ONBATT)) { sleepval = pollfreq; - ups->linestate = 1; setflag(&ups->status, ST_ONLINE); } } @@ -701,7 +698,6 @@ static void ups_on_batt(utype_t *ups) do_notify(ups, NOTIFY_ONBATT); setflag(&ups->status, ST_ONBATT); clearflag(&ups->status, ST_ONLINE); - clearflag(&ups->status, ST_OFF); } static void ups_on_line(utype_t *ups) @@ -723,7 +719,6 @@ static void ups_on_line(utype_t *ups) setflag(&ups->status, ST_ONLINE); clearflag(&ups->status, ST_ONBATT); - clearflag(&ups->status, ST_OFF); } /* create the flag file if necessary */ @@ -1047,7 +1042,8 @@ static int is_ups_critical(utype_t *ups) return 1; } - if (flag_isset(ups->status, ST_BYPASS)) { + if (ups->bypassstate == 1 + || flag_isset(ups->status, ST_BYPASS)) { upslogx(LOG_WARNING, "UPS [%s] was last known to be on BYPASS " "and currently is not communicating, assuming dead", @@ -1055,7 +1051,8 @@ static int is_ups_critical(utype_t *ups) return 1; } - if (flag_isset(ups->status, ST_OFF) && offdurationtime >= 0) { + if (ups->offstate == 1 + || (offdurationtime >= 0 && flag_isset(ups->status, ST_OFF))) { upslogx(LOG_WARNING, "UPS [%s] was last known to be (administratively) OFF " "and currently is not communicating, assuming dead", @@ -1073,7 +1070,8 @@ static int is_ups_critical(utype_t *ups) } /* administratively OFF (long enough, see OFFDURATION) */ - if (flag_isset(ups->status, ST_OFF) && offdurationtime >= 0 && ups->linestate == 0) { + if (flag_isset(ups->status, ST_OFF) && offdurationtime >= 0 + && (ups->linestate == 0 || ups->offstate == 1)) { upslogx(LOG_WARNING, "UPS [%s] is reported as (administratively) OFF", ups->sys); diff --git a/clients/upsmon.h b/clients/upsmon.h index 3caba49b3a..25c760b479 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -62,6 +62,10 @@ typedef struct { /* handle suppression of COMMOK and ONLINE at startup */ int commstate; /* these start at -1, and only */ int linestate; /* fire on a 0->1 transition */ + int offstate; /* fire on a 0->1 transition, may */ + /* be delayed vs. seeing OFF state */ + int bypassstate; /* fire on a 0->1 transition; */ + /* delays not implemented now */ /* see detailed comment for pollfail_log_throttle_max in upsmon.c * about handling of poll failure log throttling (syslog storage I/O) From e345b973fc0e6bcf1322de3ad44cb00e5719dc11 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 16 Oct 2023 17:29:18 +0200 Subject: [PATCH 1202/1232] clients/upsmon.{c,h}: refactor restoring pollfreq (from alert to normal) [#2108] Signed-off-by: Jim Klimov --- clients/upsmon.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 6fa0117db7..68ab3380fe 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -164,6 +164,16 @@ static int flag_isset(int num, int flag) return ((num & flag) == flag); } +static int try_restore_pollfreq(utype_t *ups) { + /* Use relaxed pollfreq if we are not in a hardware + * power state that is prone to UPS disappearance */ + if (!flag_isset(ups->status, ST_ONBATT | ST_OFF | ST_BYPASS | ST_CAL)) { + sleepval = pollfreq; + return 1; + } + return 0; +} + static void wall(const char *text) { #ifndef WIN32 @@ -638,11 +648,7 @@ static void ups_is_notoff(utype_t *ups) if (flag_isset(ups->status, ST_OFF)) { /* actual change */ do_notify(ups, NOTIFY_NOTOFF); clearflag(&ups->status, ST_OFF); - - if (!flag_isset(ups->status, ST_ONBATT)) { - sleepval = pollfreq; - setflag(&ups->status, ST_ONLINE); - } + try_restore_pollfreq(ups); } } @@ -672,11 +678,7 @@ static void ups_is_notbypass(utype_t *ups) if (flag_isset(ups->status, ST_BYPASS)) { /* actual change */ do_notify(ups, NOTIFY_NOTBYPASS); clearflag(&ups->status, ST_BYPASS); - - if (!flag_isset(ups->status, ST_ONBATT)) { - sleepval = pollfreq; - setflag(&ups->status, ST_ONLINE); - } + try_restore_pollfreq(ups); } } @@ -702,13 +704,13 @@ static void ups_on_batt(utype_t *ups) static void ups_on_line(utype_t *ups) { + try_restore_pollfreq(ups); + if (flag_isset(ups->status, ST_ONLINE)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); return; } - sleepval = pollfreq; - upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* ignore the first OL at startup, otherwise send the notifier */ From 43552f9ff2c6ace1aa945340a86422b797515972 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 17 Oct 2023 10:02:18 +0200 Subject: [PATCH 1203/1232] drivers/libusb1.c: nut_libusb_open(): do not keep Bus/Device/BusPort pointers to random malloc() block if we did not get a number to print there from libusb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid (un-)pretty prints like: 0.031364 [D2] - Bus: 006 0.031366 [D2] - Bus Port: ▒UV▒▒U 0.031368 [D2] - Device: 001 Signed-off-by: Jim Klimov --- drivers/libusb1.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 84d5ebdbc3..17f4b8f740 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -268,6 +268,8 @@ static int nut_libusb_open(libusb_device_handle **udevp, } else { upsdebugx(1, "%s: invalid libusb bus number %i", __func__, bus_num); + free(curDevice->Bus); + curDevice->Bus = NULL; } device_addr = libusb_get_device_address(device); @@ -290,6 +292,8 @@ static int nut_libusb_open(libusb_device_handle **udevp, } else { upsdebugx(1, "%s: invalid libusb device address %" PRIu8, __func__, device_addr); + free(curDevice->Device); + curDevice->Device = NULL; } } @@ -305,6 +309,8 @@ static int nut_libusb_open(libusb_device_handle **udevp, } else { upsdebugx(1, "%s: invalid libusb bus number %i", __func__, bus_port); + free(curDevice->BusPort); + curDevice->BusPort = NULL; } #endif From 0659f9f8f0e5c8f69c6d14ce28ccb40dc5926fae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 09:49:35 +0200 Subject: [PATCH 1204/1232] NEWS.adoc: announce the new apc_modbus driver [#139, #2063] Signed-off-by: Jim Klimov --- NEWS.adoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index fb6ba84db1..cee3197c4e 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -191,6 +191,28 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. * fix to clean obsoleted readings (if any) AFTER getting new info from an `apcupsd` daemon, to avoid the gap when NUT driver knows nothing [#2007] + - apc_modbus driver was introduced, to cover the feature gap between existing + NUT drivers for APC hardware and the actual USB-connected devices (or their + firmwares) released since roughly 2010, which deprecated standard USB HID + support in favor of Modbus-based protocol which is used across the board + (also with their network management cards). The new driver can monitor APC + UPS devices over TCP and Serial connections, as well as USB with a patched + libmodbus (check https://github.com/EchterAgo/libmodbus/commits/rtu_usb + for now, PR pending). [#139, #2063] + * For a decade until this driver got introduced, people were advised to + use apcupsd project as the actual program which talks to a device, and + NUT apcupsd-ups driver to relay information back and forth. This was a + limited solution due to lack of command and variable setting support, + as well as relaying of just some readings (just whatever apcupsd exposes, + further constrained by what our driver knows to re-translate), with + little leverage for NUT to tap into everything the device has to offer. + There were also issues on some systems due to packaging (e.g. marking + NUT and apcupsd as competing implementations of the same features) which + required clumsy workarounds to get both installed and running. Finally, + there is a small matter of long-term viability of that approach: last + commits to apcupsd sources were in 2017 (with last release 3.14.14 in + May 2016): https://sourceforge.net/p/apcupsd/svn/HEAD/tree/ + - NUT for Windows: * Ability to build NUT for Windows, last tackled with a branch based on NUT v2.6.5 a decade ago, has been revived with the 2.8.x era codebase [#5]. From 55b3db7935544123b6bf89cf2a110a9184eb44d4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 09:56:30 +0200 Subject: [PATCH 1205/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: revise service dependencies for apcupsd-ups relay driver Signed-off-by: Jim Klimov --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index 2d2c126dbb..4a9e538e35 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -9,7 +9,7 @@ # is to just pick out some strings relevant for tracking config changes. # # Copyright (C) 2016-2020 Eaton -# Copyright (C) 2020-2022 Jim Klimov +# Copyright (C) 2020-2023 Jim Klimov # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -479,8 +479,18 @@ upsconf_getDriverMedia() { # particular system's physics, both serial and network media may need USB). CURR_DRV="`upsconf_getDriver "$1"`" || return $? case "$CURR_DRV" in - *netxml*|*snmp*|*ipmi*|*powerman*|*-mib*|*avahi*|*apcupsd*) + *netxml*|*snmp*|*ipmi*|*powerman*|*-mib*|*avahi*) printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; + *apcupsd-ups*) + # Relay from a nearby apcupsd network server into NUT ecosystem: + CURR_PORT="`upsconf_getPort "$1"`" || CURR_PORT="" + case "$CURR_PORT" in + *localhost*|*127.0.0.1*|*::1*) + printf '%s\n%s\n' "$CURR_DRV" "network-localhost" ; return ;; + *) + printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; + esac + ;; *usb*) printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; nutdrv_qx) # May be direct serial or USB From c01403bbe0bfd4f8a5a2dd4039d948c6e104fa7d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 11:27:21 +0200 Subject: [PATCH 1206/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: update a comment Signed-off-by: Jim Klimov --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index 4a9e538e35..4e24b94097 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -171,7 +171,7 @@ fi # Cache needed bits of ups.conf to speed up later parsing. Note that these # data are needed for most operations, and populated by upslist_readFile() UPSCONF_DATA="" -# Subset of normalized data above that only has sections, drivers and ports +# Subset of normalized data above that only has sections, drivers and ports (SDP) UPSCONF_DATA_SDP="" # List of configured UPSes in the config-file From b52bd036b503811a96ba1ebf2fbda1c3165962c3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 11:27:47 +0200 Subject: [PATCH 1207/1232] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: handle service dependencies for apc_modbus [#139, #2063] Signed-off-by: Jim Klimov --- .../upsdrvsvcctl/nut-driver-enumerator.sh.in | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index 4e24b94097..56a5004c82 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -491,6 +491,33 @@ upsconf_getDriverMedia() { printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; esac ;; + *apc_modbus*) + CURR_PORT="`upsconf_getPort "$1"`" || CURR_PORT="" + CURR_PORTTYPE="`upsconf_getValue "$1" 'porttype'`" || CURR_PORTTYPE="" + case "$CURR_PORTTYPE" in + *usb*) + printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; + *serial*) + printf '%s\n%s\n' "$CURR_DRV" "serial" ; return ;; + *) # default depends on driver build (against libmodbus + # version with or without support for usb) + # TOTHINK: Check for presence of config values like + # vendorid (USB) or baud (Serial)? They are optional + # with reasonable defaults anyway... + case "$CURR_PORT" in + *auto*) + printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; + /*) + printf '%s\n%s\n' "$CURR_DRV" "serial" ; return ;; + *localhost*|*127.0.0.1*|*::1*) + printf '%s\n%s\n' "$CURR_DRV" "network-localhost" ; return ;; + *) + printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; + esac + # returns are above, but just in case - have a fallback: + printf '%s\n%s\n' "$CURR_DRV" "" ; return ;; + esac + ;; *usb*) printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; nutdrv_qx) # May be direct serial or USB From a1cc676aedad9d22ac4d8e28162ce48cdd744a63 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 11:35:58 +0200 Subject: [PATCH 1208/1232] configure.ac: relax the check warning for gmtime_[rs] and localtime_[rs] As long as we have one, it is okay Closes: #2115 Signed-off-by: Jim Klimov --- configure.ac | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index aee139e079..102d03027e 100644 --- a/configure.ac +++ b/configure.ac @@ -728,9 +728,31 @@ dnl# [], [AC_MSG_WARN([Required C library routine not found; try adding __EXTEN dnl These appear with CFLAGS="-std=c99 -D_POSIX_C_SOURCE=200112L": dnl# Methods below currently do not cause build errors for C99+ modes so are dnl# not tested as thoroughly as those further below: -AC_CHECK_FUNCS(strtok_r fileno localtime_r localtime_s gmtime_r gmtime_s sigemptyset sigaction, +AC_CHECK_FUNCS(strtok_r fileno sigemptyset sigaction, [], [AC_MSG_WARN([Required C library routine not found; try adding -D_POSIX_C_SOURCE=200112L])]) +dnl For these we have a fallback implementation via the other, +dnl if at least one is available, so initial check is quiet. +dnl This typically pops up in POSIX vs. Windows builds: +AC_CHECK_FUNCS(localtime_r localtime_s gmtime_r gmtime_s, + [], []) + +AC_MSG_CHECKING([for at least one gmtime implementation]) +AS_IF([test x"${ac_cv_func_gmtime_s}-${ac_cv_func_gmtime_r}" = "xno-no"], [ + AC_MSG_RESULT([no]) + AC_MSG_WARN([Required C library routine gmtime_s nor gmtime_r was not found; try adding -D_POSIX_C_SOURCE=200112L]) + ],[ + AC_MSG_RESULT([yes]) + ]) + +AC_MSG_CHECKING([for at least one localtime implementation]) +AS_IF([test x"${ac_cv_func_localtime_s}-${ac_cv_func_localtime_r}" = "xno-no"], [ + AC_MSG_RESULT([no]) + AC_MSG_WARN([Required C library routine localtime_s nor localtime_r was not found; try adding -D_POSIX_C_SOURCE=200112L]) + ],[ + AC_MSG_RESULT([yes]) + ]) + AC_LANG_PUSH([C]) AC_CHECK_HEADER([string.h], From 33a97c841d759300438194123617474465b2acbc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:10:28 +0200 Subject: [PATCH 1209/1232] drivers/dummy-ups.c: clarify some debug messages Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 3b4be2436c..dacc5b7ff0 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -254,15 +254,16 @@ void upsdrv_updateinfo(void) if (0 != stat (fn, &fs)) #endif { - upsdebugx(2, "Can't open %s currently", fn); + upsdebugx(2, "%s: MODE_DUMMY_ONCE: Can't stat %s currently", __func__, fn); /* retry ASAP until we get a file */ memset(&datafile_stat, 0, sizeof(struct stat)); next_update = 1; } else { if (datafile_stat.st_mtime != fs.st_mtime) { upsdebugx(2, - "upsdrv_updateinfo: input file was already read once " - "to the end, but changed later - re-reading: %s", fn); + "%s: MODE_DUMMY_ONCE: input file was already read once " + "to the end, but changed later - re-reading: %s", + __func__, fn); /* updated file => retry ASAP */ next_update = 1; datafile_stat = fs; @@ -271,7 +272,7 @@ void upsdrv_updateinfo(void) } if (ctx == NULL && next_update == -1) { - upsdebugx(2, "upsdrv_updateinfo: NO-OP: input file was already read once to the end"); + upsdebugx(2, "%s: MODE_DUMMY_ONCE: NO-OP: input file was already read once to the end", __func__); dstate_dataok(); } else { /* initial parsing interrupted by e.g. TIMER line */ @@ -500,7 +501,7 @@ void upsdrv_initups(void) if (0 != stat (device_path, &datafile_stat)) #endif { - upsdebugx(2, "Can't open %s (%s) currently", device_path, fn); + upsdebugx(2, "%s: Can't stat %s (%s) currently", __func__, device_path, fn); } else { upsdebugx(2, "Located %s for device simulation data: %s", device_path, fn); } From c99484932eeb435026ddc86061086bb6a11d9d96 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:10:49 +0200 Subject: [PATCH 1210/1232] drivers/dummy-ups.c: clarify a nested if/elif/... tree Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index dacc5b7ff0..38cc04c631 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -479,16 +479,18 @@ void upsdrv_initups(void) #ifdef WIN32 || device_path[1] == ':' /* "C:\..." */ #endif - ) + ) { snprintf(fn, sizeof(fn), "%s", device_path); - else if (device_path[0] == '.') { + } else if (device_path[0] == '.') { /* "./" or "../" e.g. via CLI */ if (getcwd(fn, sizeof(fn))) { snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); - } else + } else { snprintf(fn, sizeof(fn), "%s", device_path); - } else + } + } else { snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); + } /* Update file modification timestamp (and other data) */ #ifndef WIN32 From 834bfb983dd8a52cc1518631505fd1ddbdc2c83a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:21:50 +0200 Subject: [PATCH 1211/1232] drivers/dummy-ups.c: reconcile method prototype with implem Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 38cc04c631..4c0dec8008 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -98,7 +98,7 @@ static struct stat datafile_stat; static int setvar(const char *varname, const char *val); static int instcmd(const char *cmdname, const char *extra); -static int parse_data_file(TYPE_FD upsfd); +static int parse_data_file(TYPE_FD arg_upsfd); static dummy_info_t *find_info(const char *varname); static int is_valid_data(const char* varname); static int is_valid_value(const char* varname, const char *value); From f5b495f89a8742780d5844b858956d1c87211f8c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:23:15 +0200 Subject: [PATCH 1212/1232] drivers/dummy-ups.c: clarify that "upsfd" is not really used in file-based dummy-ups; check for invalid FD for good measure (to avoid fstat() on that) Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 4c0dec8008..51bbb71a97 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -245,8 +245,13 @@ void upsdrv_updateinfo(void) /* Determine if file modification timestamp has changed * since last use (so we would want to re-read it) */ #ifndef WIN32 - /* Either successful stat is OK to fill the "fs" struct */ - if (0 != fstat (upsfd, &fs) && 0 != stat (fn, &fs)) + /* Either successful stat (zero return) is OK to + * fill the "fs" struct. Note that currently + * "upsfd" is a no-op for files, they are re-opened + * and re-parsed every time so callers can modify + * the data without complications. + */ + if ( (INVALID_FD(upsfd) || 0 != fstat (upsfd, &fs)) && 0 != stat (fn, &fs)) #else /* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA? * https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228 @@ -494,8 +499,13 @@ void upsdrv_initups(void) /* Update file modification timestamp (and other data) */ #ifndef WIN32 - /* Either successful stat is OK to fill the "datafile_stat" struct */ - if (0 != fstat (upsfd, &datafile_stat) && 0 != stat (device_path, &datafile_stat)) + /* Either successful stat (zero return) is OK to fill the + * "datafile_stat" struct. Note that currently "upsfd" is + * a no-op for files, they are re-opened and re-parsed + * every time so callers can modify the data without + * complications. + */ + if ( (INVALID_FD(upsfd) || 0 != fstat (upsfd, &datafile_stat)) && 0 != stat (device_path, &datafile_stat)) #else /* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA? * https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228 From 1956b017fa6ecb3e66bc79b710fefdd1657ca365 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:24:19 +0200 Subject: [PATCH 1213/1232] drivers/dummy-ups.c: use better-qualified "fn" rather than potentially short "device_path" to stat the paths Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 51bbb71a97..91300ba4eb 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -505,12 +505,12 @@ void upsdrv_initups(void) * every time so callers can modify the data without * complications. */ - if ( (INVALID_FD(upsfd) || 0 != fstat (upsfd, &datafile_stat)) && 0 != stat (device_path, &datafile_stat)) + if ( (INVALID_FD(upsfd) || 0 != fstat (upsfd, &datafile_stat)) && 0 != stat (fn, &datafile_stat)) #else /* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA? * https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228 */ - if (0 != stat (device_path, &datafile_stat)) + if (0 != stat (fn, &datafile_stat)) #endif { upsdebugx(2, "%s: Can't stat %s (%s) currently", __func__, device_path, fn); From 45da14345374df946bf28008afadc51b2cdd58f9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:36:16 +0200 Subject: [PATCH 1214/1232] drivers/dummy-ups.c: refactor prepare_filepath() into one helper method Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 78 +++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 91300ba4eb..dc2417e73f 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -207,6 +207,36 @@ void upsdrv_initinfo(void) dstate_addcmd("load.off"); } +static int prepare_filepath(char *fn, size_t buflen) +{ + /* Note: device_path is a global variable, + * the "port=..." value parsed in main.c */ + if (device_path[0] == '/' +#ifdef WIN32 + || device_path[1] == ':' /* "C:\..." */ +#endif + ) { + /* absolute path */ + return snprintf(fn, buflen, "%s", device_path); + } else if (device_path[0] == '.') { + /* "./" or "../" e.g. via CLI, relative to current working + * directory of the driver process... at this moment */ + if (getcwd(fn, buflen)) { + return snprintf(fn + strlen(fn), buflen - strlen(fn), "/%s", device_path); + } else { + return snprintf(fn, buflen, "%s", device_path); + } + } else { + /* assumed to be a filename in NUT config file path + * (possibly under, with direct use of dirname without dots) + * Note that we do not fiddle with file-path separator, + * modern Windows (at least via MinGW/MSYS2) supports + * the POSIX slash. + */ + return snprintf(fn, buflen, "%s/%s", confpath(), device_path); + } +} + void upsdrv_updateinfo(void) { upsdebugx(1, "upsdrv_updateinfo..."); @@ -227,20 +257,7 @@ void upsdrv_updateinfo(void) struct stat fs; char fn[SMALLBUF]; - if (device_path[0] == '/' -#ifdef WIN32 - || device_path[1] == ':' /* "C:\..." */ -#endif - ) - snprintf(fn, sizeof(fn), "%s", device_path); - else if (device_path[0] == '.') { - /* "./" or "../" e.g. via CLI */ - if (getcwd(fn, sizeof(fn))) { - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); - } else - snprintf(fn, sizeof(fn), "%s", device_path); - } else - snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); + prepare_filepath(fn, sizeof(fn)); /* Determine if file modification timestamp has changed * since last use (so we would want to re-read it) */ @@ -480,22 +497,7 @@ void upsdrv_initups(void) #endif } - if (device_path[0] == '/' -#ifdef WIN32 - || device_path[1] == ':' /* "C:\..." */ -#endif - ) { - snprintf(fn, sizeof(fn), "%s", device_path); - } else if (device_path[0] == '.') { - /* "./" or "../" e.g. via CLI */ - if (getcwd(fn, sizeof(fn))) { - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); - } else { - snprintf(fn, sizeof(fn), "%s", device_path); - } - } else { - snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); - } + prepare_filepath(fn, sizeof(fn)); /* Update file modification timestamp (and other data) */ #ifndef WIN32 @@ -732,21 +734,7 @@ static int parse_data_file(TYPE_FD arg_upsfd) { ctx = (PCONF_CTX_t *)xmalloc(sizeof(PCONF_CTX_t)); - if (device_path[0] == '/' -#ifdef WIN32 - || device_path[1] == ':' /* "C:\..." */ -#endif - ) - snprintf(fn, sizeof(fn), "%s", device_path); - else if (device_path[0] == '.') { - /* "./" or "../" e.g. via CLI */ - if (getcwd(fn, sizeof(fn))) { - snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", device_path); - } else - snprintf(fn, sizeof(fn), "%s", device_path); - } else - snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); - + prepare_filepath(fn, sizeof(fn)); pconf_init(ctx, upsconf_err); if (!pconf_file_begin(ctx, fn)) From 4dc9eae4d42c6cedef9e535be3f766d87f2e3a81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:38:44 +0200 Subject: [PATCH 1215/1232] drivers/dummy-ups.c: avoid blank line in debug logs Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index dc2417e73f..61f1fe0be0 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -657,7 +657,7 @@ static dummy_info_t *find_info(const char *varname) return item; } - upsdebugx(2, "find_info: unknown variable: %s\n", varname); + upsdebugx(2, "find_info: unknown variable: %s", varname); return NULL; } From 76e2939e217d39aaf721a81aac01b6d359bad794 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 12:49:02 +0200 Subject: [PATCH 1216/1232] drivers/dummy-ups.c: bump (C) and version due to recent changes Signed-off-by: Jim Klimov --- drivers/dummy-ups.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 61f1fe0be0..e14149a4a7 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -2,6 +2,7 @@ Copyright (C) 2005 - 2015 Arnaud Quette + 2014 - 2023 Jim Klimov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,7 +48,7 @@ #include "dummy-ups.h" #define DRIVER_NAME "Device simulation and repeater driver" -#define DRIVER_VERSION "0.16" +#define DRIVER_VERSION "0.17" /* driver description structure */ upsdrv_info_t upsdrv_info = From 2db24c38bbe4aa6c7c967d401eac2eda99ea51a8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 13:18:33 +0200 Subject: [PATCH 1217/1232] tests/NIT/nit.sh: better filter the processes we look at after sandbox_start_drivers() if debugging 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 4b132224ba..6f81279c28 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -739,7 +739,7 @@ sandbox_start_drivers() { sleep 5 if shouldDebug ; then - (ps -ef || ps -xawwu) 2>/dev/null | grep -E '(ups|nut|dummy)' || true + (ps -ef || ps -xawwu) 2>/dev/null | grep -E '(ups|nut|dummy|'"`basename "$0"`"')' | grep -vE '(ssh|startups|grep)' || true fi } From 664097bdc7c5e825d445cf2f02c7c7eb0bc24e53 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 13:18:55 +0200 Subject: [PATCH 1218/1232] tests/NIT/nit.sh: testcase_sandbox_start_drivers_after_upsd(): bump timeout and explain why Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 6f81279c28..b09133dd31 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -830,7 +830,12 @@ testcase_sandbox_start_drivers_after_upsd() { sandbox_start_drivers log_info "[testcase_sandbox_start_drivers_after_upsd] Query driver state from UPSD by UPSC after driver startup" - COUNTDOWN=60 + # Timing issues: upsd starts, we wait 10 sec, drivers start and init, + # at 20 sec upsd does not see them yet, at 30 sec the sockets connect + # but info does not come yet => may be "driver stale", finally at + # 40+(drv)/50+(upsd) sec a DUMPALL is processed (regular 30-sec loop?) - + # so tightly near a minute until we have sturdy replies. + COUNTDOWN=90 while [ "$COUNTDOWN" -gt 0 ]; do # For query errors or known wait, keep looping runcmd upsc dummy@localhost:$NUT_PORT \ From 06eb71feb2f836627913308d3821250f79afa287 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 13:19:32 +0200 Subject: [PATCH 1219/1232] tests/NIT/nit.sh: testcase_sandbox_start_drivers_after_upsd(): fix matching expression and explain why Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index b09133dd31..a85875b1a5 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -837,10 +837,12 @@ testcase_sandbox_start_drivers_after_upsd() { # so tightly near a minute until we have sturdy replies. COUNTDOWN=90 while [ "$COUNTDOWN" -gt 0 ]; do - # For query errors or known wait, keep looping + # For query errors or known wait, keep looping. May get: + # driver.state: updateinfo + # ups.status: WAIT runcmd upsc dummy@localhost:$NUT_PORT \ && case "$CMDOUT" in - "ups.status: WAIT") ;; + *"ups.status: WAIT"*) ;; *) log_info "Got output:" ; echo "$CMDOUT" ; break ;; esac sleep 1 From 2bca73b98ed7e25f207fec6885ec8fc17f3c6a2d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 13:59:27 +0200 Subject: [PATCH 1220/1232] tests/NIT/nit.sh: tag progress/report messages emitted by test cases to help log readability Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 121 +++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 52 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index a85875b1a5..5f09f8451b 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -741,6 +741,7 @@ sandbox_start_drivers() { if shouldDebug ; then (ps -ef || ps -xawwu) 2>/dev/null | grep -E '(ups|nut|dummy|'"`basename "$0"`"')' | grep -vE '(ssh|startups|grep)' || true fi + log_info "Starting dummy-ups driver(s) for sandbox - finished" } testcase_sandbox_start_upsd_alone() { @@ -757,34 +758,46 @@ UPS2" EXPECTED_UPSLIST="`echo "$EXPECTED_UPSLIST" | tr -d '\r'`" fi - log_info "Query listing from UPSD by UPSC (driver not running yet)" - runcmd upsc -l localhost:$NUT_PORT || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" + log_info "[testcase_sandbox_start_upsd_alone] Query listing from UPSD by UPSC (driver not running yet)" + res_testcase_sandbox_start_upsd_alone=0 + runcmd upsc -l localhost:$NUT_PORT || die "[testcase_sandbox_start_upsd_alone] upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" # For windows runners (printf can do wonders, so strip CR if any): if [ x"${TOP_SRCDIR}" != x ]; then CMDOUT="`echo "$CMDOUT" | tr -d '\r'`" fi if [ x"$CMDOUT" != x"$EXPECTED_UPSLIST" ] ; then - log_error "got this reply for upsc listing when '$EXPECTED_UPSLIST' was expected: '$CMDOUT'" + log_error "[testcase_sandbox_start_upsd_alone] got this reply for upsc listing when '$EXPECTED_UPSLIST' was expected: '$CMDOUT'" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_start_upsd_alone" + res_testcase_sandbox_start_upsd_alone=1 else PASSED="`expr $PASSED + 1`" fi - log_info "Query driver state from UPSD by UPSC (driver not running yet)" + log_info "[testcase_sandbox_start_upsd_alone] Query driver state from UPSD by UPSC (driver not running yet)" runcmd upsc dummy@localhost:$NUT_PORT && { log_error "upsc was supposed to answer with error exit code: $CMDOUT" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_start_upsd_alone" + res_testcase_sandbox_start_upsd_alone=1 } # Note: avoid exact matching for stderr, because it can have Init SSL messages etc. if echo "$CMDERR" | grep 'Error: Driver not connected' >/dev/null ; then PASSED="`expr $PASSED + 1`" else - log_error "got some other reply for upsc query when 'Error: Driver not connected' was expected on stderr: '$CMDOUT'" + log_error "[testcase_sandbox_start_upsd_alone] got some other reply for upsc query when 'Error: Driver not connected' was expected on stderr: '$CMDOUT'" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_start_upsd_alone" + res_testcase_sandbox_start_upsd_alone=1 fi + + if [ "$res_testcase_sandbox_start_upsd_alone" = 0 ]; then + log_info "[testcase_sandbox_start_upsd_alone] PASSED: got just the failures expected for data server alone (driver not running yet)" + else + log_error "[testcase_sandbox_start_upsd_alone] got some unexpected failures, see above" + fi + + return $res_testcase_sandbox_start_upsd_alone } testcase_sandbox_start_upsd_after_drivers() { @@ -795,33 +808,35 @@ testcase_sandbox_start_upsd_after_drivers() { upsd -F & PID_UPSD="$!" - log_debug "Tried to start UPSD as PID $PID_UPSD" + log_debug "[testcase_sandbox_start_upsd_after_drivers] Tried to start UPSD as PID $PID_UPSD" sandbox_start_drivers sandbox_start_upsd sleep 5 - COUNTDOWN=60 + COUNTDOWN=90 while [ "$COUNTDOWN" -gt 0 ]; do # For query errors or known wait, keep looping runcmd upsc dummy@localhost:$NUT_PORT \ && case "$CMDOUT" in - "ups.status: WAIT") ;; + *"ups.status: WAIT"*) ;; *) log_info "Got output:" ; echo "$CMDOUT" ; break ;; esac sleep 1 COUNTDOWN="`expr $COUNTDOWN - 1`" done - if [ "$COUNTDOWN" -le 50 ] ; then - log_warn "Had to wait a few retries for the dummy driver to connect" + if [ "$COUNTDOWN" -le 88 ] ; then + log_warn "[testcase_sandbox_start_upsd_after_drivers] Had to wait a few retries for the dummy driver to connect" fi if [ "$COUNTDOWN" -le 1 ] ; then report_NUT_PORT - die "upsd does not respond on port ${NUT_PORT} ($?)" + die "[testcase_sandbox_start_upsd_after_drivers] upsd does not respond on port ${NUT_PORT} ($?)" fi + + log_info "[testcase_sandbox_start_upsd_after_drivers] PASSED: upsd responds on port ${NUT_PORT}" } testcase_sandbox_start_drivers_after_upsd() { @@ -843,69 +858,71 @@ testcase_sandbox_start_drivers_after_upsd() { runcmd upsc dummy@localhost:$NUT_PORT \ && case "$CMDOUT" in *"ups.status: WAIT"*) ;; - *) log_info "Got output:" ; echo "$CMDOUT" ; break ;; + *) log_info "[testcase_sandbox_start_drivers_after_upsd] Got output:" ; echo "$CMDOUT" ; break ;; esac sleep 1 COUNTDOWN="`expr $COUNTDOWN - 1`" done - if [ "$COUNTDOWN" -le 58 ] ; then - log_warn "Had to wait a few retries for the dummy driver to connect" + if [ "$COUNTDOWN" -le 88 ] ; then + log_warn "[testcase_sandbox_start_drivers_after_upsd] Had to wait a few retries for the dummy driver to connect" fi if [ "$COUNTDOWN" -le 1 ] ; then # Should not get to this, except on very laggy systems maybe - log_error "Query failed, retrying with UPSD started after drivers" + log_error "[testcase_sandbox_start_drivers_after_upsd] Query failed, retrying with UPSD started after drivers" testcase_sandbox_start_upsd_after_drivers fi if [ x"${TOP_SRCDIR}" != x ]; then - log_info "Wait for dummy UPSes with larger data sets to initialize" + log_info "[testcase_sandbox_start_drivers_after_upsd] Wait for dummy UPSes with larger data sets to initialize" for U in UPS1 UPS2 ; do - COUNTDOWN=60 + COUNTDOWN=90 # TODO: Convert to runcmd()? OUT="" while [ x"$OUT" = x"ups.status: WAIT" ] ; do OUT="`upsc $U@localhost:$NUT_PORT ups.status`" || break - [ x"$OUT" = x"ups.status: WAIT" ] || { log_info "Got output:"; echo "$OUT"; break; } + [ x"$OUT" = x"ups.status: WAIT" ] || { log_info "[testcase_sandbox_start_drivers_after_upsd] Got output:"; echo "$OUT"; break; } sleep 1 COUNTDOWN="`expr $COUNTDOWN - 1`" # Systemic error, e.g. could not create socket file? - [ "$COUNTDOWN" -lt 1 ] && die "Dummy driver did not start or respond in time" + [ "$COUNTDOWN" -lt 1 ] && die "[testcase_sandbox_start_drivers_after_upsd] Dummy driver did not start or respond in time" done - if [ "$COUNTDOWN" -le 58 ] ; then - log_warn "Had to wait a few retries for the $U driver to connect" + if [ "$COUNTDOWN" -le 88 ] ; then + log_warn "[testcase_sandbox_start_drivers_after_upsd] Had to wait a few retries for the $U driver to connect" fi done fi - log_info "Expected drivers are now responding via UPSD" + log_info "[testcase_sandbox_start_drivers_after_upsd] PASSED: Expected drivers are now responding via UPSD" } testcase_sandbox_upsc_query_model() { log_info "[testcase_sandbox_upsc_query_model] Query model from dummy device" - runcmd upsc dummy@localhost:$NUT_PORT device.model || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" + runcmd upsc dummy@localhost:$NUT_PORT device.model || die "[testcase_sandbox_upsc_query_model] upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" if [ x"$CMDOUT" != x"Dummy UPS" ] ; then - log_error "got this reply for upsc query when 'Dummy UPS' was expected: $CMDOUT" + log_error "[testcase_sandbox_upsc_query_model] got this reply for upsc query when 'Dummy UPS' was expected: $CMDOUT" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_model" else PASSED="`expr $PASSED + 1`" + log_info "[testcase_sandbox_upsc_query_model] PASSED: got expected model from dummy device: $CMDOUT" fi } testcase_sandbox_upsc_query_bogus() { log_info "[testcase_sandbox_upsc_query_bogus] Query driver state from UPSD by UPSC for bogus info" runcmd upsc dummy@localhost:$NUT_PORT ups.bogus.value && { - log_error "upsc was supposed to answer with error exit code: $CMDOUT" + log_error "[testcase_sandbox_upsc_query_bogus] upsc was supposed to answer with error exit code: $CMDOUT" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_bogus" } # Note: avoid exact matching for stderr, because it can have Init SSL messages etc. if echo "$CMDERR" | grep 'Error: Variable not supported by UPS' >/dev/null ; then PASSED="`expr $PASSED + 1`" + log_info "[testcase_sandbox_upsc_query_bogus] PASSED: got expected reply to bogus query: '$CMDERR'" else - log_error "got some other reply for upsc query when 'Error: Variable not supported by UPS' was expected on stderr: '$CMDOUT'" + log_error "[testcase_sandbox_upsc_query_bogus] got some other reply for upsc query when 'Error: Variable not supported by UPS' was expected on stderr: '$CMDERR'" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_bogus" fi @@ -916,23 +933,23 @@ testcase_sandbox_upsc_query_timer() { log_info "[testcase_sandbox_upsc_query_timer] Test that dummy-ups TIMER action changes the reported state" # Driver is set up to flip ups.status every 5 sec, so check every 3 # TODO: Any need to convert to runcmd()? - OUT1="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond on port ${NUT_PORT} ($?): $OUT1" ; sleep 3 - OUT2="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond on port ${NUT_PORT} ($?): $OUT2" + OUT1="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT1" ; sleep 3 + OUT2="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT2" OUT3="" OUT4="" if [ x"$OUT1" = x"$OUT2" ]; then sleep 3 - OUT3="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond on port ${NUT_PORT} ($?): $OUT3" + OUT3="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT3" if [ x"$OUT2" = x"$OUT3" ]; then sleep 3 - OUT4="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond on port ${NUT_PORT} ($?): $OUT4" + OUT4="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT4" fi fi if echo "$OUT1$OUT2$OUT3$OUT4" | grep "OB" && echo "$OUT1$OUT2$OUT3$OUT4" | grep "OL" ; then - log_info "OK, ups.status flips over time" + log_info "[testcase_sandbox_upsc_query_timer] PASSED: ups.status flips over time" PASSED="`expr $PASSED + 1`" else - log_error "ups.status did not flip over time" + log_error "[testcase_sandbox_upsc_query_timer] ups.status did not flip over time" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_timer" fi @@ -960,10 +977,10 @@ testcase_sandbox_python_without_credentials() { unset NUT_PASS || true "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ) ; then - log_info "OK, PyNUT did not complain" + log_info "[testcase_sandbox_python_without_credentials] PASSED: PyNUT did not complain" PASSED="`expr $PASSED + 1`" else - log_error "PyNUT complained, check above" + log_error "[testcase_sandbox_python_without_credentials] PyNUT complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_python_without_credentials" fi @@ -983,10 +1000,10 @@ testcase_sandbox_python_with_credentials() { export NUT_USER NUT_PASS "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ) ; then - log_info "OK, PyNUT did not complain" + log_info "[testcase_sandbox_python_with_credentials] PASSED: PyNUT did not complain" PASSED="`expr $PASSED + 1`" else - log_error "PyNUT complained, check above" + log_error "[testcase_sandbox_python_with_credentials] PyNUT complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_python_with_credentials" fi @@ -1003,10 +1020,10 @@ testcase_sandbox_python_with_upsmon_credentials() { export NUT_USER NUT_PASS "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ) ; then - log_info "OK, PyNUT did not complain" + log_info "[testcase_sandbox_python_with_upsmon_credentials] PASSED: PyNUT did not complain" PASSED="`expr $PASSED + 1`" else - log_error "PyNUT complained, check above" + log_error "[testcase_sandbox_python_with_upsmon_credentials] PyNUT complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_python_with_upsmon_credentials" fi @@ -1041,10 +1058,10 @@ testcase_sandbox_cppnit_without_creds() { unset NUT_PASS || true "${TOP_BUILDDIR}/tests/cppnit" ) ; then - log_info "OK, cppnit did not complain" + log_info "[testcase_sandbox_cppnit_without_creds] PASSED: cppnit did not complain" PASSED="`expr $PASSED + 1`" else - log_error "cppnit complained, check above" + log_error "[testcase_sandbox_cppnit_without_creds] cppnit complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_cppnit_without_creds" fi @@ -1069,10 +1086,10 @@ testcase_sandbox_cppnit_simple_admin() { export NUT_USER NUT_PASS NUT_SETVAR_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then - log_info "OK, cppnit did not complain" + log_info "[testcase_sandbox_cppnit_simple_admin] PASSED: cppnit did not complain" PASSED="`expr $PASSED + 1`" else - log_error "cppnit complained, check above" + log_error "[testcase_sandbox_cppnit_simple_admin] cppnit complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_cppnit_simple_admin" fi @@ -1091,10 +1108,10 @@ testcase_sandbox_cppnit_upsmon_primary() { export NUT_USER NUT_PASS NUT_PRIMARY_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then - log_info "OK, cppnit did not complain" + log_info "[testcase_sandbox_cppnit_upsmon_primary] PASSED: cppnit did not complain" PASSED="`expr $PASSED + 1`" else - log_error "cppnit complained, check above" + log_error "[testcase_sandbox_cppnit_upsmon_primary] cppnit complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_cppnit_upsmon_primary" fi @@ -1113,10 +1130,10 @@ testcase_sandbox_cppnit_upsmon_master() { export NUT_USER NUT_PASS NUT_PRIMARY_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then - log_info "OK, cppnit did not complain" + log_info "[testcase_sandbox_cppnit_upsmon_master] PASSED: cppnit did not complain" PASSED="`expr $PASSED + 1`" else - log_error "cppnit complained, check above" + log_error "[testcase_sandbox_cppnit_upsmon_master] cppnit complained, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_cppnit_upsmon_master" fi @@ -1149,7 +1166,7 @@ testcase_sandbox_nutscanner_list() { log_separator log_info "[testcase_sandbox_nutscanner_list] Call libupsclient test suite: nut-scanner on localhost:${NUT_PORT}" - log_info "Preparing LD_LIBRARY_PATH='${LD_LIBRARY_PATH_CLIENT}'" + log_info "[testcase_sandbox_nutscanner_list] Preparing LD_LIBRARY_PATH='${LD_LIBRARY_PATH_CLIENT}'" # Note: for some reason `LD_LIBRARY_PATH=... runcmd ...` loses it :\ LD_LIBRARY_PATH="${LD_LIBRARY_PATH_CLIENT}" @@ -1173,14 +1190,14 @@ testcase_sandbox_nutscanner_list() { || return if [ "${NUT_PORT}" = 3493 ] || [ x"$NUT_PORT" = x ]; then - echo "Note: not testing for suffixed port number" >&2 + echo "[testcase_sandbox_nutscanner_list] Note: not testing for suffixed port number" >&2 else echo "$CMDOUT" | grep -E 'dummy@.*'":${NUT_PORT}" \ || return fi if [ x"${TOP_SRCDIR}" = x ]; then - echo "Note: only testing one dummy device" >&2 + echo "[testcase_sandbox_nutscanner_list] Note: only testing one dummy device" >&2 else echo "$CMDOUT" | grep -E '^\[nutdev2\]$' \ && echo "$CMDOUT" | grep 'port = "UPS1@' \ @@ -1189,13 +1206,13 @@ testcase_sandbox_nutscanner_list() { || return fi ) ; then - log_info "OK, nut-scanner found all expected devices" + log_info "[testcase_sandbox_nutscanner_list] PASSED: nut-scanner found all expected devices" PASSED="`expr $PASSED + 1`" else if ( echo "$CMDERR" | grep -E "Cannot load NUT library.*libupsclient.*found.*NUT search disabled" ) ; then - log_warn "SKIP: ${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner: $CMDERR" + log_warn "[testcase_sandbox_nutscanner_list] SKIP: ${TOP_BUILDDIR}/tools/nut-scanner/nut-scanner: $CMDERR" else - log_error "nut-scanner complained or did not return all expected data, check above" + log_error "[testcase_sandbox_nutscanner_list] nut-scanner complained or did not return all expected data, check above" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_nutscanner_list" fi From 861b50ebfa742986a391a42a1621c852e84966f6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 14:15:11 +0200 Subject: [PATCH 1221/1232] tests/NIT/nit.sh: report driver PIDs when debugging Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 5f09f8451b..252f2051f1 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -727,13 +727,16 @@ sandbox_start_drivers() { #upsdrvctl -F start dummy & dummy-ups -a dummy -F & PID_DUMMYUPS="$!" + log_debug "Tried to start dummy-ups driver for 'dummy' as PID $PID_DUMMYUPS" if [ x"${TOP_SRCDIR}" != x ]; then dummy-ups -a UPS1 -F & PID_DUMMYUPS1="$!" + log_debug "Tried to start dummy-ups driver for 'UPS1' as PID $PID_DUMMYUPS1" dummy-ups -a UPS2 -F & PID_DUMMYUPS2="$!" + log_debug "Tried to start dummy-ups driver for 'UPS2' as PID $PID_DUMMYUPS2" fi sleep 5 From 9fbb5a77f862e7eab37359f4e9b47dacb38d487f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 14:18:00 +0200 Subject: [PATCH 1222/1232] tests/NIT/nit.sh: sandbox_start_drivers(): report success or failure Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 252f2051f1..0b4c3a78cb 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -744,7 +744,18 @@ sandbox_start_drivers() { if shouldDebug ; then (ps -ef || ps -xawwu) 2>/dev/null | grep -E '(ups|nut|dummy|'"`basename "$0"`"')' | grep -vE '(ssh|startups|grep)' || true fi - log_info "Starting dummy-ups driver(s) for sandbox - finished" + + if isPidAlive "$PID_DUMMYUPS" \ + && { [ x"${TOP_SRCDIR}" != x ] && isPidAlive "$PID_DUMMYUPS1" && isPidAlive "$PID_DUMMYUPS2" \ + || [ x"${TOP_SRCDIR}" = x ] ; } \ + ; then + # All drivers expected for this environment are already running + log_info "Starting dummy-ups driver(s) for sandbox - all expected processes are running" + return 0 + else + log_error "Starting dummy-ups driver(s) for sandbox - finished, but something seems to not be running" + return 1 + fi } testcase_sandbox_start_upsd_alone() { From 21fe0284b13a3aaaa40efed6d62c26ba8b5c38a1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 14:19:00 +0200 Subject: [PATCH 1223/1232] common/common.c: optionally support NUT_DEBUG_PID envvar presence to include PID number in debug-level identifiers Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++++ UPGRADING.adoc | 5 +++++ common/common.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index fb6ba84db1..1ced95eb5a 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -139,6 +139,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. of UID/GID (everywhere), which makes troubleshooting harder (e.g. lack of access to config files or USB device nodes). Now we have it [#1694] + - A `NUT_DEBUG_PID` envvar (presence) support was added to add current + process ID to tags with debug-level identifiers. This may be useful + when many NUT daemons write to the same console or log file. [#2118] + - huawei-ups2000 is now known to support more devices, noted in docs and for auto-detection [#1448, #1684] diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 9e0e989a01..6cdfd2bae5 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -128,6 +128,11 @@ Changes from 2.8.0 to 2.8.1 and exposed in `libnutscan.so` builds in particular - API version for the public library was bumped [#317] +- A `NUT_DEBUG_PID` envvar (presence) support was added to add current + process ID to tags with debug-level identifiers. This may be useful + when many NUT daemons write to the same console or log file, such as + in containers/plugins for Home Assistant, storage appliances, etc. [#2118] + - `configure` script, reference init-script and packaging templates updated to eradicate `@PIDPATH@/nut` ambiguity in favor of `@ALTPIDPATH@` for the unprivileged processes vs. `@PIDPATH@` for those running as root [#1719] diff --git a/common/common.c b/common/common.c index c12587ae1d..7633a3defa 100644 --- a/common/common.c +++ b/common/common.c @@ -1519,6 +1519,7 @@ void s_upsdebug_with_errno(int level, const char *fmt, ...) { va_list va; char fmt2[LARGEBUF]; + static int NUT_DEBUG_PID = -1; /* Note: Thanks to macro wrapping, we do not quite need this * test now, but we still need the "level" value to report @@ -1534,7 +1535,18 @@ void s_upsdebug_with_errno(int level, const char *fmt, ...) * can help limit this debug stream quicker, than experimentally picking ;) */ if (level > 0) { int ret; - ret = snprintf(fmt2, sizeof(fmt2), "[D%d] %s", level, fmt); + + if (NUT_DEBUG_PID < 0) { + NUT_DEBUG_PID = (getenv("NUT_DEBUG_PID") != NULL); + } + + if (NUT_DEBUG_PID) { + /* Note that we re-request PID every time as it can + * change during the run-time (forking etc.) */ + ret = snprintf(fmt2, sizeof(fmt2), "[D%d:%" PRIiMAX "] %s", level, (intmax_t)getpid(), fmt); + } else { + ret = snprintf(fmt2, sizeof(fmt2), "[D%d] %s", level, fmt); + } if ((ret < 0) || (ret >= (int) sizeof(fmt2))) { syslog(LOG_WARNING, "upsdebug_with_errno: snprintf needed more than %d bytes", LARGEBUF); @@ -1564,6 +1576,7 @@ void s_upsdebugx(int level, const char *fmt, ...) { va_list va; char fmt2[LARGEBUF]; + static int NUT_DEBUG_PID = -1; if (nut_debug_level < level) return; @@ -1571,7 +1584,19 @@ void s_upsdebugx(int level, const char *fmt, ...) /* See comments above in upsdebug_with_errno() - they apply here too. */ if (level > 0) { int ret; - ret = snprintf(fmt2, sizeof(fmt2), "[D%d] %s", level, fmt); + + if (NUT_DEBUG_PID < 0) { + NUT_DEBUG_PID = (getenv("NUT_DEBUG_PID") != NULL); + } + + if (NUT_DEBUG_PID) { + /* Note that we re-request PID every time as it can + * change during the run-time (forking etc.) */ + ret = snprintf(fmt2, sizeof(fmt2), "[D%d:%" PRIiMAX "] %s", level, (intmax_t)getpid(), fmt); + } else { + ret = snprintf(fmt2, sizeof(fmt2), "[D%d] %s", level, fmt); + } + if ((ret < 0) || (ret >= (int) sizeof(fmt2))) { syslog(LOG_WARNING, "upsdebugx: snprintf needed more than %d bytes", LARGEBUF); From ecc5031ffe6d1b0f44d0f8e4980f273985fd9ce7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 14:26:37 +0200 Subject: [PATCH 1224/1232] tests/NIT/nit.sh: use NUT_DEBUG_PID envvar to help test-log readability Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0b4c3a78cb..440d9d2e1f 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -34,6 +34,9 @@ export TZ LANG LC_ALL NUT_QUIET_INIT_SSL="true" export NUT_QUIET_INIT_SSL +NUT_DEBUG_PID="true" +export NUT_DEBUG_PID + log_separator() { echo "" >&2 echo "================================" >&2 From 7a30529dae0a216418e13cbcf75bf1cd745ef57a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 16:17:01 +0200 Subject: [PATCH 1225/1232] tests/NIT/nit.sh: use log_separator() before sandbox_forget_configs() in testgroup*() Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 440d9d2e1f..8635784493 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1256,6 +1256,7 @@ testgroup_sandbox() { testcases_sandbox_cppnit testcases_sandbox_nutscanner + log_separator sandbox_forget_configs } @@ -1263,6 +1264,8 @@ testgroup_sandbox_python() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcases_sandbox_python + + log_separator sandbox_forget_configs } @@ -1270,6 +1273,8 @@ testgroup_sandbox_cppnit() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcases_sandbox_cppnit + + log_separator sandbox_forget_configs } @@ -1277,6 +1282,8 @@ testgroup_sandbox_cppnit_simple_admin() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcase_sandbox_cppnit_simple_admin + + log_separator sandbox_forget_configs } @@ -1284,6 +1291,8 @@ testgroup_sandbox_nutscanner() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcases_sandbox_nutscanner + + log_separator sandbox_forget_configs } From ec9172ef69081286e6bbb82b8ff13d0bbb47bb37 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 16:31:23 +0200 Subject: [PATCH 1226/1232] tests/NIT/nit.sh: tag more progress messages with respective testcase; revise upsd stopping after testcase_upsd_allow_no_device() Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 8635784493..5bde7cad6d 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -551,11 +551,11 @@ testcase_upsd_no_configs_at_all() { log_info "[testcase_upsd_no_configs_at_all] Test UPSD without configs at all" upsd -F if [ "$?" = 0 ]; then - log_error "upsd should fail without configs" + log_error "[testcase_upsd_no_configs_at_all] upsd should fail without configs" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_upsd_no_configs_at_all" else - log_info "OK, upsd failed to start in wrong conditions" + log_info "[testcase_upsd_no_configs_at_all] PASSED: upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } @@ -566,11 +566,11 @@ testcase_upsd_no_configs_driver_file() { generatecfg_upsd_trivial upsd -F if [ "$?" = 0 ]; then - log_error "upsd should fail without driver config file" + log_error "[testcase_upsd_no_configs_driver_file] upsd should fail without driver config file" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_upsd_no_configs_driver_file" else - log_info "OK, upsd failed to start in wrong conditions" + log_info "[testcase_upsd_no_configs_driver_file] PASSED: upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } @@ -582,11 +582,11 @@ testcase_upsd_no_configs_in_driver_file() { generatecfg_ups_trivial upsd -F if [ "$?" = 0 ]; then - log_error "upsd should fail without drivers defined in config file" + log_error "[testcase_upsd_no_configs_in_driver_file] upsd should fail without drivers defined in config file" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_upsd_no_configs_in_driver_file" else - log_info "OK, upsd failed to start in wrong conditions" + log_info "[testcase_upsd_no_configs_in_driver_file] PASSED: upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } @@ -602,7 +602,7 @@ testcase_upsd_allow_no_device() { fi upsd -F & PID_UPSD="$!" - log_debug "Tried to start UPSD as PID $PID_UPSD" + log_debug "[testcase_upsd_allow_no_device] Tried to start UPSD as PID $PID_UPSD" sleep 2 COUNTDOWN=60 @@ -616,57 +616,65 @@ testcase_upsd_allow_no_device() { if [ "$COUNTDOWN" -le 50 ] ; then # Should not get to this, except on very laggy systems maybe - log_warn "Had to wait a few retries for the UPSD process to appear" + log_warn "[testcase_upsd_allow_no_device] Had to wait a few retries for the UPSD process to appear" fi + res_testcase_upsd_allow_no_device=0 if [ "$COUNTDOWN" -gt 0 ] \ && isPidAlive "$PID_UPSD" \ ; then - log_info "OK, upsd is running" + log_info "[testcase_upsd_allow_no_device] OK, upsd is running" PASSED="`expr $PASSED + 1`" log_separator - log_info "Query listing from UPSD by UPSC (no devices configured yet) to test that UPSD responds to UPSC" + log_info "[testcase_upsd_allow_no_device] Query listing from UPSD by UPSC (no devices configured yet) to test that UPSD responds to UPSC" if runcmd upsc -l localhost:$NUT_PORT ; then : else # Note: avoid exact matching for stderr, because it can have Init SSL messages etc. if echo "$CMDERR" | grep "Error: Server disconnected" >/dev/null ; then - log_warn "Retry once to rule out laggy systems" + log_warn "[testcase_upsd_allow_no_device] Retry once to rule out laggy systems" sleep 3 runcmd upsc -l localhost:$NUT_PORT fi if echo "$CMDERR" | grep "Error: Server disconnected" >/dev/null ; then - log_warn "Retry once more to rule out very laggy systems" + log_warn "[testcase_upsd_allow_no_device] Retry once more to rule out very laggy systems" sleep 15 runcmd upsc -l localhost:$NUT_PORT fi - [ "$CMDRES" = 0 ] || die "upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" + [ "$CMDRES" = 0 ] || die "[testcase_upsd_allow_no_device] upsd does not respond on port ${NUT_PORT} ($?): $CMDOUT" fi if [ -n "$CMDOUT" ] ; then - log_error "got reply for upsc listing when none was expected: $CMDOUT" + log_error "[testcase_upsd_allow_no_device] got reply for upsc listing when none was expected: $CMDOUT" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_upsd_allow_no_device" + res_testcase_upsd_allow_no_device=1 else - log_info "OK, empty response as expected" + log_info "[testcase_upsd_allow_no_device] OK, empty response as expected" PASSED="`expr $PASSED + 1`" fi else - log_error "upsd was expected to be running although no devices are defined; is ups.conf populated?" + log_error "[testcase_upsd_allow_no_device] upsd was expected to be running although no devices are defined; is ups.conf populated?" ls -la "$NUT_CONFPATH/" || true FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_upsd_allow_no_device" + res_testcase_upsd_allow_no_device=1 report_NUT_PORT - - UPSD_RES=0 - kill -15 $PID_UPSD - wait $PID_UPSD || UPSD_RES=$? - log_error "upsd exit-code was: $UPSD_RES" - return $UPSD_RES fi + log_info "[testcase_upsd_allow_no_device] stopping upsd: $PID_UPSD" + UPSD_RES=0 kill -15 $PID_UPSD - wait $PID_UPSD + wait $PID_UPSD || UPSD_RES=$? + if [ "$res_testcase_upsd_allow_no_device" = 0 ] ; then + log_info "[testcase_upsd_allow_no_device] upsd exit-code was: $UPSD_RES" + else + log_error "[testcase_upsd_allow_no_device] upsd exit-code was: $UPSD_RES" + fi + if [ "$UPSD_RES" != 0 ]; then + return $UPSD_RES + fi + return $res_testcase_upsd_allow_no_device } testgroup_upsd_invalid_configs() { From 72c985dee3f368152646015e0a33531a2e3c2b7f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 18 Oct 2023 16:54:23 +0200 Subject: [PATCH 1227/1232] tests/NIT/nit.sh: testcase_sandbox_nutscanner_list(): fix reporting * report why a test case failed sanity-checks; * avoid grep output spilling to test log to avoid confusion; * revise that exactly expected port count was seen (that was the confusion); * use log_*() in that sanity-check block Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 5bde7cad6d..1feac3ed65 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1205,6 +1205,10 @@ testcase_sandbox_nutscanner_list() { LD_LIBRARY_PATH="${LD_LIBRARY_PATH_ORIG}" export LD_LIBRARY_PATH + log_info "[testcase_sandbox_nutscanner_list] findings from nut-scanner:" + echo "$CMDOUT" + log_info "[testcase_sandbox_nutscanner_list] inspecting these findings from nut-scanner..." + # Note: the reported "driver" string is not too helpful as a "nutclient". # In practice this could be a "dummy-ups" repeater or "clone" driver, # or some of the config elements needed for upsmon (lacking creds/role) @@ -1215,22 +1219,40 @@ testcase_sandbox_nutscanner_list() { || return if [ "${NUT_PORT}" = 3493 ] || [ x"$NUT_PORT" = x ]; then - echo "[testcase_sandbox_nutscanner_list] Note: not testing for suffixed port number" >&2 + log_info "[testcase_sandbox_nutscanner_list] Note: not testing for suffixed port number" >&2 else echo "$CMDOUT" | grep -E 'dummy@.*'":${NUT_PORT}" \ - || return + || { + log_error "[testcase_sandbox_nutscanner_list] dummy@... not found" >&2 + return 1 + } fi if [ x"${TOP_SRCDIR}" = x ]; then - echo "[testcase_sandbox_nutscanner_list] Note: only testing one dummy device" >&2 + log_info "[testcase_sandbox_nutscanner_list] Note: only testing one dummy device" >&2 else echo "$CMDOUT" | grep -E '^\[nutdev2\]$' \ && echo "$CMDOUT" | grep 'port = "UPS1@' \ && echo "$CMDOUT" | grep -E '^\[nutdev3\]$' \ && echo "$CMDOUT" | grep 'port = "UPS2@' \ - || return + || { + log_error "[testcase_sandbox_nutscanner_list] something about UPS1/UPS2 not found" >&2 + return 1 + } fi - ) ; then + + if [ x"${TOP_SRCDIR}" = x ]; then + PORTS_WANT=1 + else + PORTS_WANT=3 + fi + PORTS_SEEN="`echo "$CMDOUT" | grep -Ec 'port *='`" + + if [ "$PORTS_WANT" != "$PORTS_SEEN" ]; then + log_error "[testcase_sandbox_nutscanner_list] Too many 'port=' lines: want $PORTS_WANT != seen $PORTS_SEEN" >&2 + return 1 + fi + ) >/dev/null ; then log_info "[testcase_sandbox_nutscanner_list] PASSED: nut-scanner found all expected devices" PASSED="`expr $PASSED + 1`" else From 0f34b8400b001dd81ee2699e71a774c398b2c12b Mon Sep 17 00:00:00 2001 From: Axel Gembe Date: Wed, 18 Oct 2023 23:45:06 +0700 Subject: [PATCH 1228/1232] nut_usbinfo.pl: Lowercase the USB ids before inserting If we don't normalize the case before inserting VID/PID/Driver into `$vendor` we can have duplicate entries. Signed-off-by: Axel Gembe --- tools/nut-usbinfo.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index 20d72934e4..c2bbceaddf 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -304,6 +304,9 @@ sub find_usbdevs } } + $VendorID=lc($VendorID); + $ProductID=lc($ProductID); + # store data (to be optimized) # and don't overwrite actual vendor names with empty values if( (!$vendorName{$VendorID}) or (($vendorName{$VendorID} eq "") and ($VendorName ne "")) ) From 7701368c554c711a1b7c86b558e0c8fc273ba212 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 19 Oct 2023 01:40:11 +0200 Subject: [PATCH 1229/1232] tests/NIT/nit.sh: avoid printing "Error:..." in successful cases This confuses CI log analyzer Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 1feac3ed65..9cee5082a7 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -945,9 +945,9 @@ testcase_sandbox_upsc_query_bogus() { # Note: avoid exact matching for stderr, because it can have Init SSL messages etc. if echo "$CMDERR" | grep 'Error: Variable not supported by UPS' >/dev/null ; then PASSED="`expr $PASSED + 1`" - log_info "[testcase_sandbox_upsc_query_bogus] PASSED: got expected reply to bogus query: '$CMDERR'" + log_info "[testcase_sandbox_upsc_query_bogus] PASSED: got expected reply to bogus query" else - log_error "[testcase_sandbox_upsc_query_bogus] got some other reply for upsc query when 'Error: Variable not supported by UPS' was expected on stderr: '$CMDERR'" + log_error "[testcase_sandbox_upsc_query_bogus] got some other reply for upsc query when 'Error: Variable not supported by UPS' was expected on stderr: stderr:'$CMDERR' / stdout:'$CMDOUT'" FAILED="`expr $FAILED + 1`" FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_bogus" fi From 425a2d6bcaec75dc3ca295c8af6cf0d9e2852c81 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 19 Oct 2023 12:26:57 +0200 Subject: [PATCH 1230/1232] GitIgnore .ci*.txt* if some are left over in the NUT CI farm work area Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d027bcec9..26991a7786 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ Makefile.in *.adoc*.tmp *.txt*.tmp /cppcheck*.xml +/.ci*.txt* /.ci*.log /.ci*.log.* .dirstamp From 71710c265b40d9db5060c4bbe782ea49de4c1b85 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 19 Oct 2023 12:26:57 +0200 Subject: [PATCH 1231/1232] GitIgnore .ci*.txt* if some are left over in the NUT CI farm work area Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d027bcec9..26991a7786 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ Makefile.in *.adoc*.tmp *.txt*.tmp /cppcheck*.xml +/.ci*.txt* /.ci*.log /.ci*.log.* .dirstamp From df296a8d79ff8ed5bd975c10482c1af7abb2e763 Mon Sep 17 00:00:00 2001 From: Axel Gembe Date: Sat, 30 Sep 2023 18:04:07 +0700 Subject: [PATCH 1232/1232] apc_modbus: Support for APC Modbus protocol This adds a new driver called `apc_modbus` to support the APC Modbus protocol over serial ports, TCP connections and USB ports. For USB support to work it needs a [patched `libmodbus` that has support for the APC USB Modbus encapsulation](https://github.com/EchterAgo/libmodbus/commits/rtu_usb). If a `libmodbus` without USB support is detected the driver will build with just the serial and TCP/IP support. Signed-off-by: Axel Gembe --- AUTHORS | 6 + data/driver.list.in | 8 + docs/man/Makefile.am | 9 +- docs/man/apc_modbus.txt | 76 +++ docs/nut.dict | 10 +- drivers/Makefile.am | 4 +- drivers/apc_modbus.c | 1328 +++++++++++++++++++++++++++++++++++++ m4/nut_check_libmodbus.m4 | 6 + tools/nut-usbinfo.pl | 3 +- 9 files changed, 1444 insertions(+), 6 deletions(-) create mode 100644 docs/man/apc_modbus.txt create mode 100644 drivers/apc_modbus.c diff --git a/AUTHORS b/AUTHORS index 4c9619133a..3eaff4f4ef 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,12 @@ # if you want to hide at the bottom, that's fine by me. Just clarify # your preference when submitting changes to this file. +N: Axel Gembe +E: axel@gembe.net +W: http://axel.gembe.net/ +D: Added APC Modbus support +P: rsa4096/43109AAC 11E6 515C B8A4 26C6 07C1 36A4 1CB3 AA21 4310 9AAC + N: Stephen Brown E: steve@datalimbo.net W: http://www.datalimbo.net/ diff --git a/data/driver.list.in b/data/driver.list.in index 8d9b56e0b0..1bb1bee82d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -80,7 +80,15 @@ "APC" "ups" "3" "SMC2200BI-BR" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/557 "APC" "ups" "3" "Smart-UPS (USB)" "USB" "usbhid-ups" "APC" "ups" "3" "Smart-UPS 750 (SMT750I, USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "Smart-UPS 1500 (SMT1500I, USB)" "USB" "usbhid-ups" "APC" "ups" "3" "Smart-UPS X 750 (SMX750I, USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "Smart-UPS X 1500 (SMX1500I, USB)" "USB" "usbhid-ups" +"APC" "ups" "3" "SMC2200BI-BR" "USB" "apc_modbus" # https://github.com/networkupstools/nut/issues/557 +"APC" "ups" "3" "Smart-UPS (USB)" "USB" "apc_modbus" +"APC" "ups" "3" "Smart-UPS 750 (SMT750I, USB)" "USB" "apc_modbus" +"APC" "ups" "3" "Smart-UPS 1500 (SMT1500I, USB)" "USB" "apc_modbus" +"APC" "ups" "3" "Smart-UPS X 750 (SMX750I, USB)" "USB" "apc_modbus" +"APC" "ups" "3" "Smart-UPS X 1500 (SMX1500I, USB)" "USB" "apc_modbus" "APC" "ups" "3" "CS500" "USB" "usbhid-ups (limited data available)" # https://github.com/networkupstools/nut/issues/1776#issuecomment-1377784584 "APC" "ups" "1" "Back-UPS" "940-0095A/C cables" "genericups upstype=1" "APC" "ups" "1" "Back-UPS" "940-0020B/C cables" "genericups upstype=2" diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 083f52c036..03e4d1bca0 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -666,7 +666,8 @@ SRC_MODBUS_PAGES = phoenixcontact_modbus.txt \ generic_modbus.txt \ huawei-ups2000.txt \ socomec_jbus.txt \ - adelsystem_cbi.txt + adelsystem_cbi.txt \ + apc_modbus.txt if ! SOME_DRIVERS if WITH_MANS @@ -674,7 +675,8 @@ MAN_MODBUS_PAGES = phoenixcontact_modbus.8 \ generic_modbus.8 \ huawei-ups2000.8 \ socomec_jbus.8 \ - adelsystem_cbi.8 + adelsystem_cbi.8 \ + apc_modbus.8 endif WITH_MANS if WITH_MODBUS @@ -685,7 +687,8 @@ HTML_MODBUS_MANS = phoenixcontact_modbus.html \ generic_modbus.html \ huawei-ups2000.html \ socomec_jbus.html \ - adelsystem_cbi.html + adelsystem_cbi.html \ + apc_modbus.html endif ! SOME_DRIVERS # (--with-linux_i2c) diff --git a/docs/man/apc_modbus.txt b/docs/man/apc_modbus.txt new file mode 100644 index 0000000000..d26f7787cd --- /dev/null +++ b/docs/man/apc_modbus.txt @@ -0,0 +1,76 @@ +APC_MODBUS(8) +============= + +NAME +---- + +apc_modbus - Driver for APC Smart-UPS Modbus protocol + +SUPPORTED HARDWARE +------------------ + +Generally this driver should work for all the APC Modbus UPS devices. Some +devices might expose more than is currently supported, like multiple phases. + +Tested with the following hardware: + + - SMT1500 (Smart-UPS 1500, Firmware 9.6) + - SMX750 (Smart-UPS X 750, Firmware 10.1) + - SMX1500 (Smart-UPS X 1500, Firmware 15.0) + +Note that you will have to enable Modbus communication. In the front panel of +the UPS, go to Advanced Menu mode, under Configuration and enable Modbus. + +EXTRA ARGUMENTS +--------------- + +This driver also supports the following optional settings: + +include::nut_usb_addvars.txt[] + +*porttype*='value':: +Set the type of the port used. Available values are serial for RS232/485 based +connections, tcp for TCP/IP connections and usb for USB connections. + +*port*='value':: +Depending on the port type you can select a port here. For usb only auto is +supported, for serial you can pass a device path like /dev/ttyS0 and for tcp you +can pass a hostname with optional port like example.com:502. + +*baudrate*='num':: +Set the speed of the serial connection. The default baudrate is 9600. + +*parity*='value':: +Set the parity of the serial connection. Available values are N for none, E for +even and O for odd. The default parity is N (none). + +*databits*='num':: +Set the data bits of the serial connection. The default databits is 8. + +*stopbits*='num':: +Set the stop bits of the serial connection. The default stopbits is 1. + +*slaveid*='num':: +Set the Modbus slave id. The default slave id is 1. + +*response_timeout_ms*='num':: +Set the Modbus response timeout. The default timeout is set by libmodbus. It can +be good to set a higher timeout on TCP connections with high latency. + +AUTHORS +------- + +* Axel Gembe + +SEE ALSO +-------- + +The core driver +~~~~~~~~~~~~~~~~ + +linkman:nutupsdrv[8], linkman:ups.conf[5] + +Internet resources +~~~~~~~~~~~~~~~~~~ + +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/nut.dict b/docs/nut.dict index 745fd4636f..16b9ffb2f0 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,5 @@ -personal_ws-1.1 en 3247 utf-8 +personal_ws-1.1 en 3255 utf-8 +AAC AAS ABI ACFAIL @@ -85,6 +86,7 @@ Autobook Autoconfigure Autostartup Avocent +Axel Axxium BATGNn BATNn @@ -421,6 +423,7 @@ Gammons Gandi Gaspar Gathman +Gembe GenTestFail Gert GetUPSVars @@ -1798,6 +1801,7 @@ d'un da daisychain daisychained +databits datacenter datadir datagrams @@ -2616,6 +2620,7 @@ pollinterval pollonly popa portname +porttype powercom powerdev powerdown @@ -2753,6 +2758,7 @@ rootfs rootfs'es rq rqt +rsa rsync rts runlevel @@ -2834,6 +2840,7 @@ sitop sizeof ske skel +slaveid slavesync slewrate slibtool @@ -2888,6 +2895,7 @@ stdupsv stopAtConnect stopAtEntry stopIP +stopbits str strace strarr diff --git a/drivers/Makefile.am b/drivers/Makefile.am index e24243ab91..f6c369dd6d 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -58,7 +58,7 @@ SERIAL_USB_DRIVERLIST = \ nutdrv_qx NEONXML_DRIVERLIST = netxml-ups MACOSX_DRIVERLIST = macosx-ups -MODBUS_DRIVERLIST = phoenixcontact_modbus generic_modbus huawei-ups2000 socomec_jbus adelsystem_cbi +MODBUS_DRIVERLIST = phoenixcontact_modbus generic_modbus huawei-ups2000 socomec_jbus adelsystem_cbi apc_modbus LINUX_I2C_DRIVERLIST = asem pijuice POWERMAN_DRIVERLIST = powerman-pdu IPMI_DRIVERLIST = nut-ipmipsu @@ -294,6 +294,8 @@ generic_modbus_SOURCES = generic_modbus.c generic_modbus_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS) adelsystem_cbi_SOURCES = adelsystem_cbi.c adelsystem_cbi_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS) +apc_modbus_SOURCES = apc_modbus.c $(LIBUSB_IMPL) hidparser.c usb-common.c +apc_modbus_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS) $(LIBUSB_LIBS) # Huawei UPS2000 driver # (this is both a Modbus and a serial driver) diff --git a/drivers/apc_modbus.c b/drivers/apc_modbus.c new file mode 100644 index 0000000000..dc401ca6c7 --- /dev/null +++ b/drivers/apc_modbus.c @@ -0,0 +1,1328 @@ +/* apc_modbus.c - Driver for APC Modbus UPS + * Copyright © 2023 Axel Gembe + * + * 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" +#if defined NUT_MODBUS_HAS_USB +#include "nut_libusb.h" +#include "libhid.h" +#include "hidparser.h" +#endif /* defined NUT_MODBUS_HAS_USB */ +#include "timehead.h" +#include "nut_stdint.h" + +#include +#include + +#include + +#define DRIVER_NAME "NUT APC Modbus driver" +#define DRIVER_VERSION "0.01" + +#if defined NUT_MODBUS_HAS_USB + +/* APC */ +#define APC_VENDORID 0x051D + +/* USB IDs device table */ +static usb_device_id_t apc_modbus_usb_device_table[] = { + { USB_DEVICE(APC_VENDORID, 0x0003), NULL }, + + /* Terminating entry */ + { 0, 0, NULL } +}; + +#endif /* defined NUT_MODBUS_HAS_USB */ + +/* Constants */ +static const uint8_t modbus_default_slave_id = 1; + +static const int modbus_rtu_default_baudrate = 9600; +static const char modbus_rtu_default_parity = 'N'; +static const int modbus_rtu_default_databits = 8; +static const int modbus_rtu_default_stopbits = 1; + +static const uint16_t modbus_tcp_default_port = 502; + +#if defined NUT_MODBUS_HAS_USB +static const HIDNode_t modbus_rtu_usb_usage_rx = 0xff8600fc; +static const HIDNode_t modbus_rtu_usb_usage_tx = 0xff8600fd; +#endif /* defined NUT_MODBUS_HAS_USB */ + +/* Variables */ +static modbus_t *modbus_ctx = NULL; +#if defined NUT_MODBUS_HAS_USB +static USBDevice_t usbdevice; +static USBDeviceMatcher_t *reopen_matcher = NULL; +static USBDeviceMatcher_t *regex_matcher = NULL; +static USBDeviceMatcher_t *best_matcher = NULL; +static int is_usb = 0; +#endif /* defined NUT_MODBUS_HAS_USB */ +static int is_open = 0; +static double power_nominal; +static double realpower_nominal; + +/* Function declarations */ +static int _apc_modbus_read_inventory(void); + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Axel Gembe \n", + DRV_BETA, + {NULL} +}; + +typedef enum { + APC_MODBUS_VALUE_TYPE_INT = 0, + APC_MODBUS_VALUE_TYPE_UINT, + APC_MODBUS_VALUE_TYPE_STRING +} apc_modbus_value_types; + +static const apc_modbus_value_types apc_modbus_value_types_max = APC_MODBUS_VALUE_TYPE_STRING; + +typedef struct { + apc_modbus_value_types type; + const char *format; + int scale; + void *variable_ptr; + union { + int64_t int_value; + uint64_t uint_value; + char *string_value; + } data; +} apc_modbus_value_t; + +typedef struct { + int (*apc_to_nut)(const apc_modbus_value_t *value, char *output, size_t output_len); + int (*nut_to_apc)(const char *value, uint16_t *output, size_t output_len); +} apc_modbus_converter_t; + +/* Converts a Modbus string to a C string. + * See MPAO-98KJ7F_EN section 1.3.3 Strings. + * + * Needs to remove leading zeroes, trailing spaces and translate characters in + * the range 0x20-0x7e as a different character. + * Zero termination is optional, so the output buffer needs to be 1 byte + * longer to add zero termination. */ +static int _apc_modbus_to_string(const uint16_t *value, const size_t value_len, char *output, size_t output_len) +{ + char *op; + size_t i; + + if (value == NULL || output == NULL) { + /* Invalid parameters */ + return 0; + } + + if ((value_len * sizeof(uint16_t)) + 1 > output_len) { + /* Output buffer too small */ + return 0; + } + + op = output; + + /* Find first non-zero register */ + for (i = 0; i < value_len; i++) { + if (value[i] != 0) + break; + } + + if (i < value_len) { + /* The second character could be zero, skip if it is */ + if (((value[i] & 0xff00) >> 8) == 0) { + *(op++) = (char)(value[i] & 0xff); + i++; + } + + /* For each remaining register, take MSB then LSB into string */ + for (; i < value_len; i++) { + *(op++) = (char)((value[i] & 0xff00) >> 8); + *(op++) = (char)(value[i] & 0xff); + } + } + + /* Add zero termination */ + *op = 0; + + assert(op < output + output_len); + + /* Find last non-zero/space */ + for (op--; op > output && (*op == 0 || *op == ' '); op--); + + /* Cut off rest of string */ + *(op + 1) = 0; + + /* Translate charaters outside of 0x20-0x7e range to spaces */ + for (; op > output; op--) { + if (*op < 0x20 || *op > 0x7e) { + *op = ' '; + } + } + + return 1; +} + +/* Converts a Modbus integer to a uint64_t. + * See MPAO-98KJ7F_EN section 1.3.1 Numbers. */ +static int _apc_modbus_to_uint64(const uint16_t *value, const size_t value_len, uint64_t *output) +{ + size_t i; + + if (value == NULL || output == NULL) { + /* Invalid parameters */ + return 0; + } + + *output = 0; + for (i = 0; i < value_len; i++) { + *output = (*output << 16) | value[i]; + } + + return 1; +} + +static int _apc_modbus_to_int64(const uint16_t *value, const size_t value_len, int64_t *output) +{ + size_t shiftval; + + if (!_apc_modbus_to_uint64(value, value_len, (uint64_t*)output)) { + return 0; + } + + shiftval = (8 * (sizeof(int64_t) - (value_len * sizeof(uint16_t)))); + *output <<= shiftval; + *output >>= shiftval; + + return 1; +} + +static int _apc_modbus_to_double(const apc_modbus_value_t *value, double *output) +{ + int factor; + + if (value == NULL || output == NULL) { + /* Invalid parameters */ + return 0; + } + + factor = 1 << value->scale; + + assert(value->type <= apc_modbus_value_types_max); + switch (value->type) { + case APC_MODBUS_VALUE_TYPE_INT: + *output = (double)value->data.int_value / factor; + break; + case APC_MODBUS_VALUE_TYPE_UINT: + *output = (double)value->data.uint_value / factor; + break; + case APC_MODBUS_VALUE_TYPE_STRING: + return 0; + } + + return 1; +} + +static int _apc_modbus_double_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + double double_value; + const char *format; + int res; + + if (output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (!_apc_modbus_to_double(value, &double_value)) { + return 0; + } + + if (value->variable_ptr) { + *((double*)value->variable_ptr) = double_value; + } + + format = "%f"; + if (value->format != NULL) + format = value->format; + +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + res = snprintf(output, output_len, format, double_value); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif + if (res < 0 || (size_t)res > output_len) { + return 0; + } + + return 1; +} + +static apc_modbus_converter_t _apc_modbus_double_conversion = { _apc_modbus_double_to_nut, NULL }; + +static int _apc_modbus_power_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + double double_value; + const char *format; + int res; + + if (output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (!_apc_modbus_to_double(value, &double_value)) { + return 0; + } + + if (value->variable_ptr) { + /* variable_ptr points to the nominal value */ + double_value = (double_value / 100.0) * *((double*)value->variable_ptr); + } + + format = "%f"; + if (value->format != NULL) + format = value->format; + +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + res = snprintf(output, output_len, format, double_value); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif + if (res < 0 || (size_t)res > output_len) { + return 0; + } + + return 1; +} + +static apc_modbus_converter_t _apc_modbus_power_conversion = { _apc_modbus_power_to_nut, NULL }; + +static int _apc_modbus_voltage_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + if (value == NULL || output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (value->type != APC_MODBUS_VALUE_TYPE_UINT) { + return 0; + } + + if (value->data.uint_value == 0xffff) { + /* Not applicable */ + strncpy(output, "NA", output_len); + return 1; + } + + return _apc_modbus_double_to_nut(value, output, output_len); +} + +static apc_modbus_converter_t _apc_modbus_voltage_conversion = { _apc_modbus_voltage_to_nut, NULL }; + +static int _apc_modbus_efficiency_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + char *cause; + + if (value == NULL || output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (value->type != APC_MODBUS_VALUE_TYPE_INT) { + return 0; + } + + switch (value->data.int_value) { + case -1: + cause = "NotAvailable"; + break; + case -2: + cause = "LoadTooLow"; + break; + case -3: + cause = "OutputOff"; + break; + case -4: + cause = "OnBattery"; + break; + case -5: + cause = "InBypass"; + break; + case -6: + cause = "BatteryCharging"; + break; + case -7: + cause = "PoorACInput"; + break; + case -8: + cause = "BatteryDisconnected"; + break; + default: + return _apc_modbus_double_to_nut(value, output, output_len); + } + + strncpy(output, cause, output_len); + + return 1; +} + +static apc_modbus_converter_t _apc_modbus_efficiency_conversion = { _apc_modbus_efficiency_to_nut, NULL }; + +static int _apc_modbus_status_change_cause_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + char *cause; + + if (value == NULL || output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (value->type != APC_MODBUS_VALUE_TYPE_UINT) { + return 0; + } + + switch (value->data.uint_value) { + case 0: + cause = "SystemInitialization"; + break; + case 1: + cause = "HighInputVoltage"; + break; + case 2: + cause = "LowInputVoltage"; + break; + case 3: + cause = "DistortedInput"; + break; + case 4: + cause = "RapidChangeOfInputVoltage"; + break; + case 5: + cause = "HighInputFrequency"; + break; + case 6: + cause = "LowInputFrequency"; + break; + case 7: + cause = "FreqAndOrPhaseDifference"; + break; + case 8: + cause = "AcceptableInput"; + break; + case 9: + cause = "AutomaticTest"; + break; + case 10: + cause = "TestEnded"; + break; + case 11: + cause = "LocalUICommand"; + break; + case 12: + cause = "ProtocolCommand"; + break; + case 13: + cause = "LowBatteryVoltage"; + break; + case 14: + cause = "GeneralError"; + break; + case 15: + cause = "PowerSystemError"; + break; + case 16: + cause = "BatterySystemError"; + break; + case 17: + cause = "ErrorCleared"; + break; + case 18: + cause = "AutomaticRestart"; + break; + case 19: + cause = "DistortedInverterOutput"; + break; + case 20: + cause = "InverterOutputAcceptable"; + break; + case 21: + cause = "EPOInterface"; + break; + case 22: + cause = "InputPhaseDeltaOutOfRange"; + break; + case 23: + cause = "InputNeutralNotConnected"; + break; + case 24: + cause = "ATSTransfer"; + break; + case 25: + cause = "ConfigurationChange"; + break; + case 26: + cause = "AlertAsserted"; + break; + case 27: + cause = "AlertCleared"; + break; + case 28: + cause = "PlugRatingExceeded"; + break; + case 29: + cause = "OutletGroupStateChange"; + break; + case 30: + cause = "FailureBypassExpired"; + break; + default: + cause = "Unknown"; + break; + } + + strncpy(output, cause, output_len); + + return 1; +} + +static apc_modbus_converter_t _apc_modbus_status_change_cause_conversion = { _apc_modbus_status_change_cause_to_nut, NULL }; + +static int _apc_modbus_date_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len) +{ + struct tm *tm_info; + time_t time_stamp; + const time_t start_offset = 946684800; /* 2000-01-01 00:00 */ + + if (value == NULL || output == NULL || output_len == 0) { + /* Invalid parameters */ + return 0; + } + + if (value->type != APC_MODBUS_VALUE_TYPE_UINT) { + return 0; + } + + time_stamp = ((int64_t)value->data.uint_value * 86400) + start_offset; + tm_info = gmtime(&time_stamp); + strftime(output, output_len, "%Y-%m-%d", tm_info); + + return 1; +} + +static apc_modbus_converter_t _apc_modbus_date_conversion = { _apc_modbus_date_to_nut, NULL }; + +typedef struct { + const char *nut_variable_name; + size_t modbus_addr; + size_t modbus_len; /* Number of uint16_t registers */ + apc_modbus_value_types value_type; + apc_modbus_converter_t *value_converter; + const char *value_format; + int value_scale; + void *variable_ptr; +} apc_modbus_register_t; + +/* 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_MODBUS_VALUE_TYPE_STRING, NULL, "%s", 0, NULL }, + { "ups.model", 532, 16, APC_MODBUS_VALUE_TYPE_STRING, NULL, "%s", 0, NULL }, /* also device.model, filled automatically */ + { "ups.serial", 564, 8, APC_MODBUS_VALUE_TYPE_STRING, NULL, "%s", 0, NULL }, /* also device.serial, filled automatically */ + { "ups.power.nominal", 588, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.0f", 0, &power_nominal }, + { "ups.realpower.nominal", 589, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.0f", 0, &realpower_nominal }, + { "ups.mfr.date", 591, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "battery.date", 595, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "ups.id", 596, 8, APC_MODBUS_VALUE_TYPE_STRING, NULL, "%s", 0, NULL }, + { NULL, 0, 0, 0, NULL, NULL, 0.0f, NULL } +}; + +static apc_modbus_register_t apc_modbus_register_map_status[] = { + { "input.transfer.reason", 2, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_status_change_cause_conversion, NULL, 0, NULL }, + { NULL, 0, 0, 0, NULL, NULL, 0.0f, NULL } +}; + +static apc_modbus_register_t apc_modbus_register_map_dynamic[] = { + { "battery.runtime", 128, 2, APC_MODBUS_VALUE_TYPE_UINT, NULL, "%u", 0, NULL }, + { "battery.charge", 130, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.2f", 9, NULL }, + { "battery.voltage", 131, 1, APC_MODBUS_VALUE_TYPE_INT, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, + { "battery.date.maintenance", 133, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "battery.temperature", 135, 1, APC_MODBUS_VALUE_TYPE_INT, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, + { "ups.load", 136, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.2f", 8, NULL }, + { "ups.realpower", 136, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_power_conversion, "%.2f", 8, &realpower_nominal }, + { "ups.power", 138, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_power_conversion, "%.2f", 8, &power_nominal }, + { "output.current", 140, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, + { "output.voltage", 142, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.2f", 6, NULL }, + { "output.frequency", 144, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, + { "experimental.output.energy", 145, 2, APC_MODBUS_VALUE_TYPE_UINT, NULL, "%u", 0, NULL }, + { "input.voltage", 151, 1, APC_MODBUS_VALUE_TYPE_UINT, &_apc_modbus_voltage_conversion, "%.2f", 6, NULL }, + { "ups.efficiency", 154, 1, APC_MODBUS_VALUE_TYPE_INT, &_apc_modbus_efficiency_conversion, "%.1f", 7, NULL }, + { "ups.timer.shutdown", 155, 1, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { "ups.timer.start", 156, 1, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { "ups.timer.reboot", 157, 2, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { NULL, 0, 0, 0, NULL, NULL, 0.0f, NULL } +}; + +static apc_modbus_register_t apc_modbus_register_map_static[] = { + { "input.transfer.high", 1026, 1, APC_MODBUS_VALUE_TYPE_UINT, NULL, "%u", 0, NULL }, + { "input.transfer.low", 1027, 1, APC_MODBUS_VALUE_TYPE_UINT, NULL, "%u", 0, NULL }, + { "ups.delay.shutdown", 1029, 1, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { "ups.delay.start", 1030, 1, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { "ups.delay.reboot", 1031, 2, APC_MODBUS_VALUE_TYPE_INT, NULL, "%d", 0, NULL }, + { NULL, 0, 0, 0, NULL, NULL, 0.0f, NULL } +}; + +static void _apc_modbus_close(int free_modbus) +{ + if (modbus_ctx != NULL) { + modbus_close(modbus_ctx); + if (free_modbus) { + modbus_free(modbus_ctx); + modbus_ctx = NULL; + } + } + + is_open = 0; +} + +#if defined NUT_MODBUS_HAS_USB +static void _apc_modbus_create_reopen_matcher(void) +{ + int r; + + if (reopen_matcher != NULL) { + USBFreeExactMatcher(reopen_matcher); + reopen_matcher = NULL; + } + + r = USBNewExactMatcher(&reopen_matcher, &usbdevice); + if (r < 0) { + fatal_with_errno(EXIT_FAILURE, "USBNewExactMatcher"); + } + + reopen_matcher->next = best_matcher; + best_matcher = reopen_matcher; +} +#endif /* defined NUT_MODBUS_HAS_USB */ + +static int _apc_modbus_reopen(void) +{ + dstate_setinfo("driver.state", "reconnect.trying"); + + if (modbus_connect(modbus_ctx) < 0) { + upslogx(LOG_ERR, "%s: Unable to connect Modbus: %s", __func__, modbus_strerror(errno)); + return 0; + } + + +#if defined NUT_MODBUS_HAS_USB + /* We might have matched a new device in the modbus_connect callback. + * Because of this we want a new exact matcher. */ + best_matcher = best_matcher->next; + _apc_modbus_create_reopen_matcher(); +#endif /* defined NUT_MODBUS_HAS_USB */ + + usleep(1000000); + modbus_flush(modbus_ctx); + + is_open = 1; + + dstate_setinfo("driver.state", "reconnect.updateinfo"); + _apc_modbus_read_inventory(); + dstate_setinfo("driver.state", "quiet"); + + return 1; +} + +static useconds_t _apc_modbus_get_time_us(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ((useconds_t)tv.tv_sec * (useconds_t)1000000) + (useconds_t)tv.tv_usec; +} + +static void _apc_modbus_interframe_delay(void) +{ + /* 4.2.2 Modbus Message RTU Framing, interframe delay */ + + static useconds_t last_send_time = 0; + static const useconds_t inter_frame_delay = 35000; + useconds_t current_time, delta_time; + + current_time = _apc_modbus_get_time_us(); + delta_time = current_time - last_send_time; + + if (delta_time > inter_frame_delay) { + /* Already over the inter frame delay */ + goto interframe_delay_exit; + } + + usleep(inter_frame_delay - delta_time); + +interframe_delay_exit: + last_send_time = current_time; +} + +static void _apc_modbus_handle_error(modbus_t *ctx) +{ + static int flush_retries = 0; + int flush = 0; +#ifdef WIN32 + int wsa_error; +#endif /* WIN32 */ + + /* + * We could enable MODBUS_ERROR_RECOVERY_LINK but that would just get stuck + * in libmodbus until recovery. The only indication of this is that the + * program is stuck and debug prints by libmodbus, which we don't want to + * enable on release. + * + * Instead we detect timout errors and do a sleep + flush, on every other + * error or when flush didn't work we do a reconnect. + */ + +#ifdef WIN32 + wsa_error = WSAGetLastError(); + if (wsa_error == WSAETIMEDOUT) { + flush = 1; + } +#else + if (errno == ETIMEDOUT) { + flush = 1; + } +#endif /* WIN32 */ + + if (flush > 0 && flush_retries++ < 5) { + usleep(1000000); + modbus_flush(ctx); + } else { + flush_retries = 0; + upslogx(LOG_ERR, "%s: Closing connection", __func__); + /* Close without free, will retry connection on next update */ + _apc_modbus_close(0); + } +} + +static int _apc_modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) +{ + _apc_modbus_interframe_delay(); + + if (modbus_read_registers(ctx, addr, nb, dest) > 0) { + return 1; + } else { + upslogx(LOG_ERR, "%s: Read of %d:%d failed: %s (%s)", __func__, addr, addr + nb, modbus_strerror(errno), device_path); + _apc_modbus_handle_error(ctx); + return 0; + } +} + +static int _apc_modbus_update_value(apc_modbus_register_t *regs_info, const uint16_t *regs, const size_t regs_len) +{ + apc_modbus_value_t value; + char strbuf[33], nutvbuf[128]; + + if (regs_info == NULL || regs == NULL || regs_len == 0) { + /* Invalid parameters */ + return 0; + } + + value.type = regs_info->value_type; + value.format = regs_info->value_format; + value.scale = regs_info->value_scale; + value.variable_ptr = regs_info->variable_ptr; + + assert(regs_info->value_type <= apc_modbus_value_types_max); + switch (regs_info->value_type) { + case APC_MODBUS_VALUE_TYPE_STRING: + _apc_modbus_to_string(regs, regs_info->modbus_len, strbuf, sizeof(strbuf)); + value.data.string_value = strbuf; + break; + case APC_MODBUS_VALUE_TYPE_INT: + _apc_modbus_to_int64(regs, regs_info->modbus_len, &value.data.int_value); + break; + case APC_MODBUS_VALUE_TYPE_UINT: + _apc_modbus_to_uint64(regs, regs_info->modbus_len, &value.data.uint_value); + break; + } + + if (regs_info->value_converter != NULL) { + /* If we have a converter, use it and set the value as a string */ + if (!regs_info->value_converter->apc_to_nut(&value, nutvbuf, sizeof(nutvbuf))) { + upslogx(LOG_ERR, "%s: Failed to convert register %" PRIuSIZE ":%" PRIuSIZE, __func__, + regs_info->modbus_addr, regs_info->modbus_addr + regs_info->modbus_len); + return 0; + } + dstate_setinfo(regs_info->nut_variable_name, "%s", nutvbuf); + } else { +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + assert(regs_info->value_type <= apc_modbus_value_types_max); + switch (regs_info->value_type) { + case APC_MODBUS_VALUE_TYPE_STRING: + dstate_setinfo(regs_info->nut_variable_name, regs_info->value_format, value.data.string_value); + break; + case APC_MODBUS_VALUE_TYPE_INT: + dstate_setinfo(regs_info->nut_variable_name, regs_info->value_format, value.data.int_value); + break; + case APC_MODBUS_VALUE_TYPE_UINT: + dstate_setinfo(regs_info->nut_variable_name, regs_info->value_format, value.data.uint_value); + break; + } +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif + } + + return 1; +} + +static int _apc_modbus_process_registers(apc_modbus_register_t* values, const uint16_t *regs, const size_t regs_len, const size_t regs_offset) +{ + size_t i; + apc_modbus_register_t *v; + + for (i = 0; values[i].nut_variable_name; i++) { + v = &values[i]; + + if ((size_t)v->modbus_addr < regs_offset || (size_t)(v->modbus_addr + v->modbus_len) > regs_offset + regs_len) { + continue; + } + + _apc_modbus_update_value(v, regs + (v->modbus_addr - regs_offset), v->modbus_len); + } + + return 1; +} + +static int _apc_modbus_read_inventory(void) +{ + uint16_t regbuf[88]; + + /* Inventory Information */ + if (_apc_modbus_read_registers(modbus_ctx, 516, 88, regbuf)) { + _apc_modbus_process_registers(apc_modbus_register_map_inventory, regbuf, 88, 516); + } else { + return 0; + } + + return 1; +} + +void upsdrv_initinfo(void) +{ + if (!_apc_modbus_read_inventory()) { + fatalx(EXIT_FAILURE, "Can't read inventory information from the UPS"); + } + + dstate_setinfo("ups.mfr", "American Power Conversion"); /* also device.mfr, filled automatically */ + + dstate_setinfo("device.type", "ups"); +} + +void upsdrv_updateinfo(void) +{ + uint16_t regbuf[32]; + uint64_t value; + + if (!is_open) { + if (!_apc_modbus_reopen()) { + upsdebugx(2, "Failed to reopen modbus"); + dstate_datastale(); + return; + } + } + + alarm_init(); + status_init(); + + /* Status Data */ + if (_apc_modbus_read_registers(modbus_ctx, 0, 27, regbuf)) { + /* UPSStatus_BF, 2 registers */ + _apc_modbus_to_uint64(®buf[0], 2, &value); + if (value & (1 << 1)) { + status_set("OL"); + } + if (value & (1 << 2)) { + status_set("OB"); + } + if (value & (1 << 3)) { + status_set("BYPASS"); + } + if (value & (1 << 4)) { + status_set("OFF"); + } + if (value & (1 << 5)) { + alarm_set("General fault"); + } + if (value & (1 << 6)) { + alarm_set("Input not acceptable"); + } + if (value & (1 << 7)) { + status_set("TEST"); + } + if (value & (1 << 13)) { + status_set("HE"); /* High efficiency / ECO mode*/ + } + if (value & (1 << 21)) { + status_set("OVER"); + } + + /* SimpleSignalingStatus_BF, 1 register */ + _apc_modbus_to_uint64(®buf[18], 1, &value); + if (value & (1 << 1)) { /* ShutdownImminent */ + status_set("LB"); + } + + /* BatterySystemError_BF, 1 register */ + _apc_modbus_to_uint64(®buf[18], 1, &value); + if (value & (1 << 1)) { /* NeedsReplacement */ + status_set("RB"); + } + + /* RunTimeCalibrationStatus_BF, 1 register */ + _apc_modbus_to_uint64(®buf[24], 1, &value); + if (value & (1 << 1)) { /* InProgress */ + status_set("CAL"); + } + + _apc_modbus_process_registers(apc_modbus_register_map_status, regbuf, 27, 0); + } else { + dstate_datastale(); + return; + } + + /* Dynamic Data */ + if (_apc_modbus_read_registers(modbus_ctx, 128, 32, regbuf)) { + /* InputStatus_BF, 1 register */ + _apc_modbus_to_uint64(®buf[22], 1, &value); + if (value & (1 << 5)) { + status_set("BOOST"); + } + if (value & (1 << 6)) { + status_set("TRIM"); + } + + _apc_modbus_process_registers(apc_modbus_register_map_dynamic, regbuf, 32, 128); + } else { + dstate_datastale(); + return; + } + + /* Static Data */ + if (_apc_modbus_read_registers(modbus_ctx, 1026, 7, regbuf)) { + _apc_modbus_process_registers(apc_modbus_register_map_static, regbuf, 7, 1026); + } else { + dstate_datastale(); + return; + } + + alarm_commit(); + status_commit(); + dstate_dataok(); +} + +void upsdrv_shutdown(void) +{ + /* TODO: replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); +} + +void upsdrv_help(void) +{ +} + +void upsdrv_makevartable(void) +{ +#if defined NUT_MODBUS_HAS_USB + nut_usb_addvars(); +#endif /* defined NUT_MODBUS_HAS_USB */ + +#if defined NUT_MODBUS_HAS_USB + addvar(VAR_VALUE, "porttype", "Modbus port type (serial, tcp, usb, default=usb)"); +#else + addvar(VAR_VALUE, "porttype", "Modbus port type (serial, tcp, default=serial)"); +#endif /* defined NUT_MODBUS_HAS_USB */ + addvar(VAR_VALUE, "slaveid", "Modbus slave id (default=1)"); + addvar(VAR_VALUE, "response_timeout_ms", "Modbus response timeout in milliseconds"); + + /* Serial RTU parameters */ + addvar(VAR_VALUE, "baudrate", "Modbus serial RTU communication speed in baud (default=9600)"); + addvar(VAR_VALUE, "parity", "Modbus serial RTU parity (N=none, E=even, O=odd, default=N)"); + addvar(VAR_VALUE, "databits", "Modbus serial RTU data bit count (default=8)"); + addvar(VAR_VALUE, "stopbits", "Modbus serial RTU stop bit count (default=1)"); +} + +#if defined NUT_MODBUS_HAS_USB +static int _apc_modbus_usb_device_match_func(USBDevice_t *hd, void *privdata) +{ + int status; + + NUT_UNUSED_VARIABLE(privdata); + + status = is_usb_device_supported(apc_modbus_usb_device_table, hd); + + switch (status) { + case POSSIBLY_SUPPORTED: + /* by default, reject, unless the productid option is given */ + if (getval("productid")) { + return 1; + } + return 0; + + case SUPPORTED: + return 1; + + case NOT_SUPPORTED: + default: + return 0; + } +} + +static USBDeviceMatcher_t apc_modbus_usb_device_matcher = { &_apc_modbus_usb_device_match_func, NULL, NULL }; + +static void _apc_modbus_usb_lib_to_nut(const modbus_usb_device_t *device, USBDevice_t *out) +{ + /* This makes a USBDevice_t from modbus_usb_device_t so we can use our matchers */ + + static char bus_buf[4], device_buf[4], bus_port_buf[4]; + + assert(device != NULL); + assert(out != NULL); + + memset(out, 0, sizeof(USBDevice_t)); + + out->VendorID = device->vid; + out->ProductID = device->pid; + out->Vendor = device->vendor_str; + out->Product = device->product_str; + out->Serial = device->serial_str; + out->bcdDevice = device->bcd_device; + + snprintf(bus_buf, sizeof(bus_buf), "%03u", device->bus); + out->Bus = bus_buf; + + snprintf(device_buf, sizeof(device_buf), "%03u", device->device_address); + out->Device = device_buf; + +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + snprintf(bus_port_buf, sizeof(bus_port_buf), "%03u", device->bus_port); + out->BusPort = bus_port_buf; +#endif +} + +static int _apc_modbus_usb_callback(const modbus_usb_device_t *device) +{ + HIDDesc_t *hid_desc; + size_t i; + HIDData_t *hid_cur_item, *hid_rtu_rx = NULL, *hid_rtu_tx = NULL; + HIDNode_t hid_cur_usage; + USBDeviceMatcher_t *current_matcher; + + if (device == NULL) { + upslogx(LOG_ERR, "%s: NULL device passed", __func__); + return -1; + } + + _apc_modbus_usb_lib_to_nut(device, &usbdevice); + + current_matcher = best_matcher; + while (current_matcher != NULL) { + if (current_matcher->match_function(&usbdevice, current_matcher->privdata) == 1) { + break; + } + + current_matcher = current_matcher->next; + } + + if (current_matcher == NULL) { + upsdebug_with_errno(1, "%s: Failed to match!", __func__); + return -1; + } + + upsdebugx(2, "%s: Matched %s %s (USB VID/PID %04x:%04x)", __func__, device->vendor_str, device->product_str, device->vid, device->pid); + + if (device->hid_report_descriptor_buf == NULL) { + upslogx(LOG_WARNING, "%s: No HID report descriptor, using defaults", __func__); + goto usb_callback_exit; + } + + upsdebugx(2, "%s: Checking %s %s (USB VID/PID %04x:%04x) report descriptors", __func__, device->vendor_str, device->product_str, device->vid, device->pid); + + hid_desc = Parse_ReportDesc(device->hid_report_descriptor_buf, (usb_ctrl_charbufsize)device->hid_report_descriptor_len); + if (!hid_desc) { + upsdebug_with_errno(1, "%s: Failed to parse report descriptor!", __func__); + return -1; + } + + for (i = 0; i < hid_desc->nitems; i++) { + hid_cur_item = &hid_desc->item[i]; + + hid_cur_usage = hid_cur_item->Path.Node[hid_cur_item->Path.Size - 1]; + + if (hid_cur_usage == modbus_rtu_usb_usage_rx) { + hid_rtu_rx = hid_cur_item; + } else if (hid_cur_usage == modbus_rtu_usb_usage_tx) { + hid_rtu_tx = hid_cur_item; + } + } + + if (hid_rtu_rx == NULL || hid_rtu_tx == NULL) { + upsdebugx(1, "%s: No Modbus USB report descriptor found", __func__); + Free_ReportDesc(hid_desc); + return -1; + } + + upsdebugx(1, "%s: Found report ids RX=0x%02x TX=0x%02x", __func__, hid_rtu_rx->ReportID, hid_rtu_tx->ReportID); + + modbus_rtu_usb_set_report_ids(modbus_ctx, hid_rtu_rx->ReportID, hid_rtu_tx->ReportID); + + Free_ReportDesc(hid_desc); + +usb_callback_exit: + dstate_setinfo("ups.vendorid", "%04x", device->vid); + dstate_setinfo("ups.productid", "%04x", device->pid); + + return 0; +} +#endif /* defined NUT_MODBUS_HAS_USB */ + +static int _apc_modbus_parse_host_port(const char *input, char *host, size_t host_buf_size, char *port, size_t port_buf_size, const uint16_t default_port) { + const char *start = input; + const char *end = input; + int port_int; + size_t host_size, port_size; + + if (*start == '[') { + start++; + end = strchr(start, ']'); + if (!end) { + upslogx(LOG_ERR, "%s: Invalid IPv6 notation", __func__); + return 0; + } + } else { + end = strchr(start, ':'); + } + + if (!end) { + /* Port is missing, use the default port */ + strncpy(host, start, host_buf_size); + snprintf(port, port_buf_size, "%u", default_port); + return 0; + } + + host_size = (size_t)(end - start); + port_size = strlen(end + 1); + + if (host_size >= host_buf_size || port_size >= port_buf_size) { + upslogx(LOG_ERR, "%s: Buffer size too small", __func__); + return 0; + } + + strncpy(host, start, host_size); + strncpy(port, end + 1, port_size); + + port_int = atoi(port); + if (port_int < 0 || port_int > 65535) { + upslogx(LOG_ERR, "%s: Port out of range", __func__); + return 0; + } + + return 1; +} + +void upsdrv_initups(void) +{ + int r; +#if defined NUT_MODBUS_HAS_USB + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; + int has_nonzero_regex; + size_t i; +#endif /* defined NUT_MODBUS_HAS_USB */ + char *val; + int rtu_baudrate; + char rtu_parity; + int rtu_databits; + int rtu_stopbits; + int slaveid; + uint32_t response_timeout_ms; + char tcp_host[256]; + char tcp_port[6]; + + val = getval("porttype"); + + if (val == NULL) { +#if defined NUT_MODBUS_HAS_USB + val = "usb"; +#else + val = "serial"; +#endif /* defined NUT_MODBUS_HAS_USB */ + } + + is_open = 0; + +#if defined NUT_MODBUS_HAS_USB + is_usb = 0; +#endif /* defined NUT_MODBUS_HAS_USB */ + + if (!strcasecmp(val, "usb")) { +#if defined NUT_MODBUS_HAS_USB + is_usb = 1; + + /* We default to USB, this is the most common connection type and does not require additional + * parameter, so we can auto-detect these. */ + + warn_if_bad_usb_port_filename(device_path); + + regex_array[0] = getval("vendorid"); + regex_array[1] = getval("productid"); + regex_array[2] = getval("vendor"); + regex_array[3] = getval("product"); + regex_array[4] = getval("serial"); + regex_array[5] = getval("bus"); + regex_array[6] = getval("device"); +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + regex_array[7] = getval("busport"); +# else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } +# endif + + has_nonzero_regex = 0; + for (i = 0; i < sizeof(regex_array) / sizeof(regex_array[0]); i++) { + if (regex_array[i] != NULL) { + has_nonzero_regex = 1; + } + } + + best_matcher = &apc_modbus_usb_device_matcher; + + if (has_nonzero_regex > 0) { + r = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); + if (r < 0) { + fatal_with_errno(EXIT_FAILURE, "USBNewRegexMatcher"); + } else if (r) { + fatalx(EXIT_FAILURE, "invalid regular expression: %s", regex_array[r]); + } + + regex_matcher->next = best_matcher; + best_matcher = regex_matcher; + } + + modbus_ctx = modbus_new_rtu_usb(MODBUS_USB_MODE_APC, _apc_modbus_usb_callback); +#else + fatalx(EXIT_FAILURE, "driver was not compiled with USB support"); +#endif /* defined NUT_MODBUS_HAS_USB */ + } else if (!strcasecmp(val, "tcp")) { + if (!_apc_modbus_parse_host_port(device_path, tcp_host, sizeof(tcp_host), tcp_port, sizeof(tcp_port), modbus_tcp_default_port)) { + fatalx(EXIT_FAILURE, "failed to parse host/port"); + } + + modbus_ctx = modbus_new_tcp_pi(tcp_host, tcp_port); + } else if (!strcasecmp(val, "serial")) { + val = getval("baudrate"); + rtu_baudrate = val ? atoi(val) : modbus_rtu_default_baudrate; + + val = getval("parity"); + rtu_parity = val ? (char)toupper(val[0]) : modbus_rtu_default_parity; + + val = getval("databits"); + rtu_databits = val ? atoi(val) : modbus_rtu_default_databits; + + val = getval("stopbits"); + rtu_stopbits = val ? atoi(val) : modbus_rtu_default_stopbits; + + modbus_ctx = modbus_new_rtu(device_path, rtu_baudrate, rtu_parity, rtu_databits, rtu_stopbits); + } + + if (modbus_ctx == NULL) { + fatalx(EXIT_FAILURE, "Unable to create the libmodbus context: %s", modbus_strerror(errno)); + } + + if (nut_debug_level > 5) { + modbus_set_debug(modbus_ctx, 1); + } + + val = getval("slaveid"); + slaveid = val ? atoi(val) : modbus_default_slave_id; + r = modbus_set_slave(modbus_ctx, slaveid); + if (r < 0) { + modbus_free(modbus_ctx); + fatalx(EXIT_FAILURE, "modbus_set_slave: invalid slave id %d", slaveid); + } + + val = getval("response_timeout_ms"); + if (val != NULL) { + response_timeout_ms = (uint32_t)strtoul(val, NULL, 0); + +#if (defined NUT_MODBUS_TIMEOUT_ARG_sec_usec_uint32) || (defined NUT_MODBUS_TIMEOUT_ARG_sec_usec_uint32_cast_timeval_fields) + r = modbus_set_response_timeout(modbus_ctx, response_timeout_ms / 1000, (response_timeout_ms % 1000) * 1000); + if (r < 0) { + modbus_free(modbus_ctx); + fatalx(EXIT_FAILURE, "modbus_set_response_timeout: error(%s)", modbus_strerror(errno)); + } +#elif (defined NUT_MODBUS_TIMEOUT_ARG_timeval_numeric_fields) + { /* see comments above */ + struct timeval to; + memset(&to, 0, sizeof(struct timeval)); + to.tv_sec = response_timeout_ms / 1000; + to.tv_usec = (response_timeout_ms % 1000) * 1000; + /* void */ modbus_set_response_timeout(modbus_ctx, &to); + } +/* #elif (defined NUT_MODBUS_TIMEOUT_ARG_timeval) // some un-castable type in fields */ +#endif /* NUT_MODBUS_TIMEOUT_ARG_* */ + } + + if (modbus_connect(modbus_ctx) == -1) { + modbus_free(modbus_ctx); + fatalx(EXIT_FAILURE, "modbus_connect: unable to connect: %s", modbus_strerror(errno)); + } + +#if defined NUT_MODBUS_HAS_USB + _apc_modbus_create_reopen_matcher(); +#endif /* defined NUT_MODBUS_HAS_USB */ + + modbus_flush(modbus_ctx); + + is_open = 1; +} + + +void upsdrv_cleanup(void) +{ + _apc_modbus_close(1); + +#if defined NUT_MODBUS_HAS_USB + USBFreeExactMatcher(reopen_matcher); + USBFreeExactMatcher(regex_matcher); +#endif /* defined NUT_MODBUS_HAS_USB */ +} diff --git a/m4/nut_check_libmodbus.m4 b/m4/nut_check_libmodbus.m4 index ea08dd3659..dbaae4968e 100644 --- a/m4/nut_check_libmodbus.m4 +++ b/m4/nut_check_libmodbus.m4 @@ -72,6 +72,8 @@ if test -z "${nut_have_libmodbus_seen}"; then AC_CHECK_FUNCS(modbus_set_byte_timeout, [], [nut_have_libmodbus=no]) AC_CHECK_FUNCS(modbus_set_response_timeout, [], [nut_have_libmodbus=no]) + AC_CHECK_FUNCS(modbus_new_rtu_usb, [nut_have_libmodbus_usb=yes], [nut_have_libmodbus_usb=no]) + dnl modbus_set_byte_timeout() and modbus_set_response_timeout() dnl in 3.0.x and 3.1.x have different args (since ~2013): the dnl older version used to accept timeout as a struct timeval @@ -180,6 +182,10 @@ modbus_set_byte_timeout(ctx, to_sec, to_usec);]) LIBMODBUS_LIBS="${LIBS}"] ) + AS_IF([test x"${nut_have_libmodbus_usb}" = x"yes"], + [AC_DEFINE([NUT_MODBUS_HAS_USB], 1, [Define to use libmodbus USB backend])] + ) + dnl restore original CFLAGS and LIBS CFLAGS="${CFLAGS_ORIG}" LIBS="${LIBS_ORIG}" diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index c2bbceaddf..590760c93d 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -211,7 +211,8 @@ sub gen_usb_files print $out_devd "};\n"; # UPower device entry (only for USB/HID devices!) - if ($vendor{$vendorId}{$productId}{"driver"} eq "usbhid-ups") + if ($vendor{$vendorId}{$productId}{"driver"} eq "usbhid-ups" || + $vendor{$vendorId}{$productId}{"driver"} eq "apc_modbus") { if (!$upowerVendorHasDevices) { if ($vendorName{$vendorId}) {