Compare commits

...

4 commits

Author SHA1 Message Date
lagertonne
ba45b20c34 WIP: Fix for nut 2.8.0
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-06-29 15:51:46 +02:00
lagertonne
0b5b61097a Add .drone.yml
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-29 12:42:58 +02:00
lagertonne
ab3256f51e nut (2.8.0-1) 2022-06-29 12:40:33 +02:00
lagertonne
b2b0c9995a new upstream 2.8.0 2022-06-29 12:37:36 +02:00
850 changed files with 137140 additions and 30130 deletions

38
.drone.yml Normal file
View file

@ -0,0 +1,38 @@
kind: pipeline
name: default
steps:
- name: Build Bullseye
image: debian:bullseye
volumes:
- name: finished_files
path: /deb_files
commands:
- apt update
- apt -y upgrade
- apt -y install --no-install-recommends build-essential equivs devscripts git rename
- git clean -f -d -x
- mk-build-deps --install --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- dpkg-buildpackage -b -uc
- rename 's/\.deb/_bullseye\.deb/' ../*.deb
- mkdir -p /deb_files/bullseye/
- cp ../*.deb /deb_files/bullseye/
- find /deb_files/
- name: gitea_release
image: plugins/gitea-release
volumes:
- name: finished_files
path: /deb_files
settings:
api_key:
from_secret: GITEA_KEY
base_url: https://git.neulandlabor.de/
files:
- /deb_files/bullseye/*
when:
event: tag
volumes:
- name: finished_files
temp: {}

16704
ChangeLog

File diff suppressed because it is too large Load diff

316
INSTALL
View file

@ -1,8 +1,8 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@ -12,97 +12,96 @@ without warranty of any kind.
Basic Installation
==================
Briefly, the shell command `./configure && make && make install'
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
The 'configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
2. Type 'make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
user, and only the 'make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
@ -113,21 +112,21 @@ Compiling For Multiple Architectures
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
own directory. To do this, you can use GNU 'make'. 'cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
@ -136,105 +135,104 @@ this:
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
using the 'lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
For packages that use the X Window System, 'configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
HP-UX 'make' updates targets which have the same time stamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
@ -242,26 +240,26 @@ and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
@ -270,101 +268,101 @@ where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
eventually be run) with '--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
'configure' Invocation
======================
`configure' recognizes the following options to control how it
'configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
`--help=short'
`--help=recursive'
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
`--cache-file=FILE'
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
'--quiet'
'--silent'
'-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
suppress all normal output, redirect it to '/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
'--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
'configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
`--no-create'
`-n'
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.

View file

@ -1,11 +1,13 @@
Installation instructions
=========================
This chapter describe the various methods for installing Network UPS Tools.
This chapter describes the various methods for installing Network UPS Tools.
Whenever it is possible, prefer <<Installing_packages, installing from packages>>.
Packagers have done an excellent and hard work at improving NUT integration into
their system.
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.
[[Installing_source]]
Installing from source
@ -16,6 +18,13 @@ These are the essential steps for compiling and installing this software.
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).
[NOTE]
.Keep in mind that...
================================================================================
@ -292,25 +301,47 @@ You can either install NUT as a binary package or as a port.
Binary package
^^^^^^^^^^^^^^
To install the main component, use the following command:
To install NUT as a package execute:
# pkg_add -r nut
# pkg install nut
Port
^^^^
The port is located under /usr/ports/sysutils/nut.
To install it, use the following command:
The port is located under +sysutils/nut+.
Use +make config+ to select configuration options, e.g. to build the optional CGI scripts.
To install it, use:
# cd /usr/ports/sysutils/nut/ && make install clean
# make install clean
You have to define WITH_NUT_CGI to build the optional CGI scripts.
USB UPS on FreeBSD
^^^^^^^^^^^^^^^^^^
Optionally, you can also install the following ports:
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:
- sysutils/nut-snmp, for the SNMP driver,
- sysutils/nut-usb, for the USB drivers,
- sysutils/nut-libupsclient, for the upsclient library.
# 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
# dmesg | tail
[...]
ugen0.2: <INNO TECH USB to Serial> at usbus0
The device file must be owned by group +uucp+ and must be group
read-/writable. In the example from above this would be
# ls -Ll /dev/ugen0.2
crw-rw---- 1 root uucp 0xa5 Mar 12 10:33 /dev/ugen0.2
If the permissions are not correct, verify that your device is registered in
+/usr/local/etc/devd/nut-usb.conf+. The vendor and product id can be found
using:
# usbconfig -u 0 -a 2 dump_device_desc
where +-u+ specifies the USB bus number and +-a+ specifies the USB device index.
You are now ready to configure NUT, and start testing and using it.

View file

@ -38,7 +38,7 @@ S: Maintained: apcsmart, belkin, bestups, cyberpower, dummycons,
P: Arnaud Quette
M: aquette.dev@gmail.com
M: ArnaudQuette@eaton.com
S: Maintained or Supported: dummy-ups, usbhid-ups, mge-shut, newmge-shut
S: Maintained or Supported: dummy-ups, usbhid-ups, mge-shut
mge-utalk, snmp-ups, ...
P: Fabio Di Niro

View file

@ -5,23 +5,33 @@ ACLOCAL_AMFLAGS = -I m4
# subdirectories to build and distribute. The order matters, as
# several subdirectories depend on stuff in "common" or tools being built first
SUBDIRS = include common clients conf data tools docs drivers \
SUBDIRS = include common clients conf data docs drivers tools \
lib scripts server tests
# Automatically update the libtool script if it becomes out-of-date
# See https://www.gnu.org/software/libtool/manual/html_node/LT_005fINIT.html
LIBTOOL_DEPS = @LIBTOOL_DEPS@
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status libtool
# COPYING is included automatically.
EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING
# ----------------------------------------------------------------------
# flags to pass to ./configure when calling "make distcheck" and "make
# distcheck-light". Try to check as many features as possible! Also
# need to give hotplug-dir and udev-dir, so that staged install does
# not fail.
# need to give augeas-lenses-dir, hotplug-dir and udev-dir, so that
# staged install does not fail.
DISTCHECK_FLAGS = --with-all --with-ssl --with-doc=auto
DISTCHECK_LIGHT_FLAGS = --with-all=auto --with-ssl=auto --with-doc=auto
DISTCHECK_VALGRIND_FLAGS = --with-all=auto --with-ssl=auto --with-doc=skip --with-valgrind CXXFLAGS='$(CXXFLAGS) -g' CFLAGS='$(CFLAGS) -g'
DISTCHECK_CONFIGURE_FLAGS = ${DISTCHECK_FLAGS} \
--with-systemdsystemunitdir='$${prefix}/lib/systemd/system' \
--with-systemdshutdowndir='$${prefix}/lib/systemd/system-shutdown' \
--with-systemdtmpfilesdir='$${prefix}/usr/lib/tmpfiles.d' \
--with-augeas-lenses-dir='$${prefix}/usr/share/augeas/lenses' \
--with-hotplug-dir='$${prefix}/etc/hotplug' \
--with-udev-dir='$${prefix}/etc/udev' \
--with-devd-dir='$${prefix}/etc/devd'
@ -29,6 +39,10 @@ DISTCHECK_CONFIGURE_FLAGS = ${DISTCHECK_FLAGS} \
distcheck-light:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_FLAGS)" distcheck
# Make a distcheck (and check in particular) with enabled valgrind and debug info
memcheck distcheck-valgrind:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_VALGRIND_FLAGS)" distcheck
# workaround the dist generated files that are also part of the distribution
# Note that distcleancheck is disabled for now, while waiting for a proper
# solution, that do not break older unix systems
@ -37,9 +51,150 @@ distcheck-light:
distcleancheck:
@:
# Quick alias for root dir recipe:
realclean: maintainer-clean
# Files made by our targets:
CLEANFILES = *-spellchecked cppcheck*.xml
DISTCLEANFILES = ChangeLog
# Most of the files generated by custom rules in the configure script
# or by autogen.sh are cleaned by the Makefile.am in their directories.
# Files below are re-created by running `configure` script and may be
# wiped by a `make distclean`:
DISTCLEANFILES += config.log configure~
#???# configure.ac~
DISTCLEANFILES += include/config.h.in~
# Files made by autotools and common rituals of the configure script,
# these are needed to run the configure script itself so are not wiped
# by a mere `make distclean`; most of these are copied by autotools
# from their installation, or made by `automake` etc. on the system
# which generates `configure`; rebuilding NUT after deleting these
# requires `autogen.sh` script to be re-run (and tools available):
MAINTAINERCLEANFILES = INSTALL
MAINTAINERCLEANFILES += aclocal.m4 config.guess config.sub
MAINTAINERCLEANFILES += configure
MAINTAINERCLEANFILES += depcomp install-sh ltmain.sh test-driver
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
# Executed after default rules
maintainer-clean-local:
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
# are included by generated Makefiles from other subdirectories, so they
# should be available during their clean-up). Just in case, we make sure
# here that their sub-distcleans complete first.
distclean-local:
@for DIR in $(SUBDIRS) ; do \
if test -f "$${DIR}/Makefile" ; then \
echo " DISTCLEAN in $${DIR}" >&2 ; \
( 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
# Hook the documentation building and validating recipes
# Note: these are optionally available (as determined during configure runs)
spellcheck spellcheck-interactive:
@RES=0; \
(cd $(builddir)/docs && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/docs/man && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/conf && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/data && $(MAKE) -s $@) || RES=$$? ; \
exit $$RES
# Note: the "all-docs" and "check-docs" targets may require tools not
# found by `configure` script (and so avoided by conventional recipes)
# 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.
doc spellcheck-sortdict \
all-docs check-docs \
man all-man man-man check-man man-html all-html:
cd $(builddir)/docs && $(MAKE) $@
check-NIT check-NIT-devel:
cd $(builddir)/tests/NIT && $(MAKE) $@
# This target adds syntax-checking for committed shell script files,
# to avoid surprises and delays in finding fatal typos after packaging
###
### Note: currently, shellcheck target calls check-scripts-syntax
### so when both are invoked at once, in the end the check is only
### executed once. Later it is anticipated that shellcheck would
### be implemented by requiring, configuring and calling the tool
### named "shellcheck" for even more code inspection and details.
### Still, there remains value in also checking the script syntax
### by the very version of the shell interpreter that would run
### these scripts in production usage of the resulting packages.
###
check-scripts-syntax:
@echo 'NOTE: modern bash complains about scripts using backticks (warning not error), which we ignore in NUT codebase for portability reasons: `...` obsolete, use $$(...)'
@RUNBASH=bash; if [ -x /bin/bash ]; then RUNBASH=/bin/bash ; else if [ -x /usr/bin/env ] ; then RUNBASH="/usr/bin/env bash"; fi; fi ; \
for F in `git ls-files || find . -type f` ; do \
case "`file "$$F"`" in \
*"Bourne-Again shell script"*) ( set -x ; $$RUNBASH -n "$$F" ; ) ;; \
*"POSIX shell script"*|*"shell script"*) ( set -x ; /bin/sh -n "$$F" ; ) ;; \
esac || { RES=$$? ; echo "ERROR: Syntax check failed for script file: $$F" >&2 ; exit $$RES ; } ; \
done
@echo 'SUCCESS: Shell scripts syntax is acceptable, no fatal issues were found'
shellcheck-disclaimer:
@echo "==============================================================================="
@echo "NOTICE: 'make shellcheck' is currently an alias for 'make check-scripts-syntax'"
@echo "Later it may become a call to the real shellcheck tool (if available on the"
@echo "build system during the configure phase)"
@echo "==============================================================================="
# Note: currently not part of shellcheck target, because the script below
# can test the logic with numerous SHELL_PROGS in a CI setting, and because
# check-scripts-syntax probably has checked the basic syntax above already.
shellcheck-nde:
cd $(srcdir)/tests && SERVICE_FRAMEWORK="selftest" ./nut-driver-enumerator-test.sh
shellcheck: shellcheck-disclaimer check-scripts-syntax
CPPCHECK = @CPPCHECK@
if HAVE_CPPCHECK
cppcheck: cppcheck-cxx11.xml cppcheck-c99.xml
# Let the analysis get regenerated due to any change in source;
# but note that with our different make implementations to support,
# we can not either $(shell find ...) nor blindly say e.g. *.cpp
# for each FS structure layer because e.g. there are no ./*.cpp
# in the root dir of the codebase (and so make complains there is
# `No rule to make target `*.cpp', needed by `cppcheck-cxx11.xml'`)
#
# Note that the actual `cppcheck` scan finds all files it likes
# (so if CPPCHECK_SRC_* misses something, it just won't trigger
# automagically a rebuild of the XML in developer working cycles).
CPPCHECK_SRC_H = $(top_srcdir)/*/*.h $(top_srcdir)/*/*/*.h
# CPPCHECK_SRC_H += $(top_srcdir)/*.h
CPPCHECK_SRC_C = $(top_srcdir)/*/*.c $(top_srcdir)/*/*/*.c
# CPPCHECK_SRC_C += $(top_srcdir)/*.cpp
CPPCHECK_SRC_CXX = $(top_srcdir)/*/*.cpp
# CPPCHECK_SRC_CXX += $(top_srcdir)/*.cpp $(top_srcdir)/*/*/*.cpp
cppcheck-cxx11.xml: $(CPPCHECK_SRC_CXX) $(CPPCHECK_SRC_H)
$(CPPCHECK) --std=c++11 --enable=all --inconclusive --xml --xml-version=2 . 2>$@
cppcheck-c99.xml: $(CPPCHECK_SRC_C) $(CPPCHECK_SRC_H)
$(CPPCHECK) --std=c99 --enable=all --inconclusive --xml --xml-version=2 . 2>$@
else !HAVE_CPPCHECK
cppcheck:
@echo "CPPCHECK analysis not available since 'cppcheck' was not found."
endif !HAVE_CPPCHECK
# ----------------------------------------------------------------------
# Automatically generate the ChangeLog from Git logs:
MAINTAINERCLEAN_FILES = ChangeLog
MAINTAINERCLEANFILES += ChangeLog
# Older boundary of the ChangeLog commits range
# It can be a tag ('v2.2.0'), a commit hash, a date, ...
@ -48,18 +203,30 @@ GITLOG_START_POINT=v2.6.0
# Force ChangeLog regeneration upon make dist (due to nonexistant 'dummy-stamp'),
# in case it has already been generated previously
# Note that the script is hard-coded to generate "ChangeLog" in the current dir
dummy-stamp:
ChangeLog: tools/gitlog2changelog.py dummy-stamp
$(top_srcdir)/tools/gitlog2changelog.py $(GITLOG_START_POINT) || \
echo "gitlog2changelog.py failed to generate the ChangeLog. See https://github.com/networkupstools/nut/commits/master" > $@
cd $(top_builddir) && \
./tools/gitlog2changelog.py $(GITLOG_START_POINT) || \
{ echo "gitlog2changelog.py failed to generate the ChangeLog. See https://github.com/networkupstools/nut/commits/master" > $@ ; }
nut_version.h include/nut_version.h:
cd $(abs_top_builddir)/include && $(MAKE) nut_version.h
tools/gitlog2changelog.py: tools/gitlog2changelog.py.in
cd $(@D) && $(MAKE) -s $(@F)
# ----------------------------------------------------------------------
# Maintainers targets: distribution signature and hashes
dist-sig:
nut-@PACKAGE_VERSION@.tar.gz: dist
nut-@PACKAGE_VERSION@.tar.gz.sig: dist-sig
nut-@PACKAGE_VERSION@.tar.gz.md5 nut-@PACKAGE_VERSION@.tar.gz.sha256: dist-hash
dist-sig: nut-@PACKAGE_VERSION@.tar.gz
rm -f nut-@PACKAGE_VERSION@.tar.gz.sig
gpg --detach-sign nut-@PACKAGE_VERSION@.tar.gz
dist-hash:
dist-hash: nut-@PACKAGE_VERSION@.tar.gz
md5sum nut-@PACKAGE_VERSION@.tar.gz > nut-@PACKAGE_VERSION@.tar.gz.md5
sha256sum nut-@PACKAGE_VERSION@.tar.gz > nut-@PACKAGE_VERSION@.tar.gz.sha256
@ -101,7 +268,7 @@ install-dirs:
@echo "Warning: 'make install-dirs' is deprecated."
@echo "Use 'make installdirs' instead."
@echo $(WARN)
make installdirs
$(MAKE) installdirs
cgi build-cgi install-cgi install-cgi-dir install-cgi-bin \
install-cgi-man install-cgi-conf install-cgi-html:
@echo "Error: 'make $@' no longer exists."
@ -117,23 +284,65 @@ snmp build-snmp install-snmp install-snmp-mgr install-snmp-man:
@echo "Use './configure --with-snmp' instead."
setver:
@echo "Error: 'make setver' no longer exists."
@echo "Edit configure.in to set version number."
package:
if test `uname -s` = "HP-UX"; then \
cd scripts/HP-UX; \
make package; \
mv NUT_HPUX_package.depot NUT_HPUX_package@PACKAGE_VERSION@.depot; \
elif test `uname -s` = "SunOS"; then \
make; \
rm -rf @prefix@; \
make install; \
cd scripts/Solaris; \
make package; \
make uninstall; \
rm -rf @prefix@; \
elif test `uname -s` = "AIX"; then \
make dist; \
cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS; \
cp scripts/Aix/nut.init nut-*.tar.gz /usr/src/packages/SOURCES; \
rpm -ba /usr/src/packages/SPECS/nut-aix.spec; \
fi;
@echo "Edit configure.ac to set version number."
# Clean the dist tarball and packages
MAINTAINERCLEANFILES_DISTBALL = nut-*.tar.gz
# HP-UX:
MAINTAINERCLEANFILES_PACKAGES = NUT_HPUX_package@PACKAGE_VERSION@.depot
# AIX as below, and RedHat-compatible (cover binary and source packages):
MAINTAINERCLEANFILES_PACKAGES += nut*rpm
# Debian-compatible (cover binary and source packages):
MAINTAINERCLEANFILES_PACKAGES += nut*deb
# Solaris SVR4 package archives:
MAINTAINERCLEANFILES_PACKAGES += NUT_solaris_*_package@PACKAGE_VERSION@.local.gz
# Newer Solaris IPS (aka "pkg(5)" format archives)
MAINTAINERCLEANFILES_PACKAGES += *.p5p
MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_DISTBALL)
MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_PACKAGES)
package: dist
DESTDIR="$(abs_builddir)/_install_pkgprotodir" ; export DESTDIR; \
rm -rf "$$DESTDIR"; \
case "`uname -s`" in \
"HP-UX") \
( cd scripts/HP-UX && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package && \
mv NUT_HPUX_package.depot $(abs_top_builddir)/NUT_HPUX_package@PACKAGE_VERSION@.depot ) ;; \
"SunOS") \
$(MAKE) $(AM_MAKEFLAGS) && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" install && \
( cd scripts/Solaris && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package ) && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" uninstall && \
rm -rf "$$DESTDIR" || \
{ echo "FAILED to produce SunOS packages, inspect '$$DESTDIR' for clues" >&2 ; exit 1; } ;; \
"AIX") \
if test -d /usr/src/packages/SPECS -a -w /usr/src/packages/SPECS ; then : ; else echo "Can not write to /usr/src/packages/SPECS" >&2 ; exit 1; fi ; \
if test -d /usr/src/packages/SOURCES -a -w /usr/src/packages/SOURCES ; then : ; else echo "Can not write to /usr/src/packages/SOURCES" >&2 ; exit 1; fi ; \
$(MAKE) $(AM_MAKEFLAGS) dist && \
cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS && \
cp scripts/Aix/nut.init nut-@PACKAGE_VERSION@.tar.gz /usr/src/packages/SOURCES && \
rpm -ba /usr/src/packages/SPECS/nut-aix.spec && \
mv /usr/src/packages/RPMS/nut*rpm $(abs_top_builddir)/ ;; \
*) echo "Unsupported OS for 'make $@' (no recipe bound)" >&2; exit 1;; \
esac
print-MAINTAINERCLEANFILES print-REALCLEANFILES:
@echo $(MAINTAINERCLEANFILES)
print-DISTCLEANFILES:
@echo $(DISTCLEANFILES)
# TODO: Recursive mode to consider patterns defined in sub-dir makefiles
git-realclean-check:
@if test -e .git && (command -v git); then \
git status --ignored || while read F ; do \
for P in $(MAINTAINERCLEANFILES) ; do \
case "$$F" in \
*/$$P) exit 1 ;; \
esac ; \
done; \
done ; \
fi

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -16,7 +16,17 @@
# top-level Makefile for NUT
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -81,27 +91,24 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = .
DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(top_srcdir)/scripts/Aix/nut-aix.spec.in \
$(top_srcdir)/scripts/avahi/nut.service.in \
$(top_srcdir)/scripts/HP-UX/nut.psf.in \
$(top_srcdir)/scripts/HP-UX/postinstall.in \
$(top_srcdir)/scripts/ufw/nut.ufw.profile.in COPYING TODO \
compile config.guess config.sub depcomp install-sh missing \
ltmain.sh
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -110,18 +117,29 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(am__DIST_COMMON)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = scripts/Aix/nut-aix.spec \
scripts/avahi/nut.service scripts/HP-UX/nut.psf \
scripts/HP-UX/postinstall scripts/ufw/nut.ufw.profile
scripts/python/module/PyNUT.py scripts/Aix/nut.init \
scripts/HP-UX/postinstall \
scripts/python/app/NUT-Monitor-py2gtk2 \
scripts/python/app/NUT-Monitor-py3qt5 \
scripts/python/module/test_nutclient.py
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@ -157,7 +175,7 @@ am__recursive_targets = \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
cscope distdir dist dist-all distcheck
cscope distdir distdir-am dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
@ -179,6 +197,18 @@ ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/scripts/Aix/nut-aix.spec.in \
$(top_srcdir)/scripts/Aix/nut.init.in \
$(top_srcdir)/scripts/HP-UX/nut.psf.in \
$(top_srcdir)/scripts/HP-UX/postinstall.in \
$(top_srcdir)/scripts/avahi/nut.service.in \
$(top_srcdir)/scripts/python/app/NUT-Monitor-py2gtk2.in \
$(top_srcdir)/scripts/python/app/NUT-Monitor-py3qt5.in \
$(top_srcdir)/scripts/python/module/PyNUT.py.in \
$(top_srcdir)/scripts/python/module/test_nutclient.py.in \
AUTHORS COPYING ChangeLog INSTALL NEWS README TODO compile \
config.guess config.sub depcomp install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@ -217,6 +247,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -228,6 +260,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -238,6 +271,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -251,6 +285,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -263,6 +298,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -280,6 +316,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -290,21 +328,32 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
# Automatically update the libtool script if it becomes out-of-date
# See https://www.gnu.org/software/libtool/manual/html_node/LT_005fINIT.html
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -324,6 +373,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -337,6 +389,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -354,6 +407,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -367,6 +421,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -392,12 +449,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -413,7 +472,7 @@ ACLOCAL_AMFLAGS = -I m4
# subdirectories to build and distribute. The order matters, as
# several subdirectories depend on stuff in "common" or tools being built first
SUBDIRS = include common clients conf data tools docs drivers \
SUBDIRS = include common clients conf data docs drivers tools \
lib scripts server tests
@ -423,20 +482,62 @@ EXTRA_DIST = INSTALL.nut LICENSE-GPL2 LICENSE-GPL3 MAINTAINERS UPGRADING
# ----------------------------------------------------------------------
# flags to pass to ./configure when calling "make distcheck" and "make
# distcheck-light". Try to check as many features as possible! Also
# need to give hotplug-dir and udev-dir, so that staged install does
# not fail.
# need to give augeas-lenses-dir, hotplug-dir and udev-dir, so that
# staged install does not fail.
DISTCHECK_FLAGS = --with-all --with-ssl --with-doc=auto
DISTCHECK_LIGHT_FLAGS = --with-all=auto --with-ssl=auto --with-doc=auto
DISTCHECK_VALGRIND_FLAGS = --with-all=auto --with-ssl=auto --with-doc=skip --with-valgrind CXXFLAGS='$(CXXFLAGS) -g' CFLAGS='$(CFLAGS) -g'
DISTCHECK_CONFIGURE_FLAGS = ${DISTCHECK_FLAGS} \
--with-systemdsystemunitdir='$${prefix}/lib/systemd/system' \
--with-systemdshutdowndir='$${prefix}/lib/systemd/system-shutdown' \
--with-systemdtmpfilesdir='$${prefix}/usr/lib/tmpfiles.d' \
--with-augeas-lenses-dir='$${prefix}/usr/share/augeas/lenses' \
--with-hotplug-dir='$${prefix}/etc/hotplug' \
--with-udev-dir='$${prefix}/etc/udev' \
--with-devd-dir='$${prefix}/etc/devd'
# Files made by our targets:
CLEANFILES = *-spellchecked cppcheck*.xml
# Most of the files generated by custom rules in the configure script
# or by autogen.sh are cleaned by the Makefile.am in their directories.
# Files below are re-created by running `configure` script and may be
# wiped by a `make distclean`:
#???# configure.ac~
DISTCLEANFILES = ChangeLog config.log configure~ include/config.h.in~
# Files made by autotools and common rituals of the configure script,
# these are needed to run the configure script itself so are not wiped
# by a mere `make distclean`; most of these are copied by autotools
# from their installation, or made by `automake` etc. on the system
# which generates `configure`; rebuilding NUT after deleting these
# requires `autogen.sh` script to be re-run (and tools available):
# ----------------------------------------------------------------------
# Automatically generate the ChangeLog from Git logs:
MAINTAINERCLEAN_FILES = ChangeLog
MAINTAINERCLEANFILES = INSTALL aclocal.m4 config.guess config.sub \
configure depcomp install-sh ltmain.sh test-driver \
m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \
m4/lt~obsolete.m4 Makefile.in .dirstamp include/config.h.in \
ChangeLog $(MAINTAINERCLEANFILES_DISTBALL) \
$(MAINTAINERCLEANFILES_PACKAGES)
# Let the analysis get regenerated due to any change in source;
# but note that with our different make implementations to support,
# we can not either $(shell find ...) nor blindly say e.g. *.cpp
# for each FS structure layer because e.g. there are no ./*.cpp
# in the root dir of the codebase (and so make complains there is
# `No rule to make target `*.cpp', needed by `cppcheck-cxx11.xml'`)
#
# Note that the actual `cppcheck` scan finds all files it likes
# (so if CPPCHECK_SRC_* misses something, it just won't trigger
# automagically a rebuild of the XML in developer working cycles).
@HAVE_CPPCHECK_TRUE@CPPCHECK_SRC_H = $(top_srcdir)/*/*.h $(top_srcdir)/*/*/*.h
# CPPCHECK_SRC_H += $(top_srcdir)/*.h
@HAVE_CPPCHECK_TRUE@CPPCHECK_SRC_C = $(top_srcdir)/*/*.c $(top_srcdir)/*/*/*.c
# CPPCHECK_SRC_C += $(top_srcdir)/*.cpp
@HAVE_CPPCHECK_TRUE@CPPCHECK_SRC_CXX = $(top_srcdir)/*/*.cpp
# Older boundary of the ChangeLog commits range
# It can be a tag ('v2.2.0'), a commit hash, a date, ...
@ -447,6 +548,17 @@ GITLOG_START_POINT = v2.6.0
# targets from old build system (pre-automake).
# supported for a period of time for backward "compatibility".
WARN = "----------------------------------------------------------------------"
# Clean the dist tarball and packages
MAINTAINERCLEANFILES_DISTBALL = nut-*.tar.gz
# HP-UX:
# AIX as below, and RedHat-compatible (cover binary and source packages):
# Debian-compatible (cover binary and source packages):
# Solaris SVR4 package archives:
# Newer Solaris IPS (aka "pkg(5)" format archives)
MAINTAINERCLEANFILES_PACKAGES = \
NUT_HPUX_package@PACKAGE_VERSION@.depot nut*rpm nut*deb \
NUT_solaris_*_package@PACKAGE_VERSION@.local.gz *.p5p
all: all-recursive
.SUFFIXES:
@ -465,15 +577,14 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -490,9 +601,17 @@ scripts/avahi/nut.service: $(top_builddir)/config.status $(top_srcdir)/scripts/a
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/HP-UX/nut.psf: $(top_builddir)/config.status $(top_srcdir)/scripts/HP-UX/nut.psf.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/python/module/PyNUT.py: $(top_builddir)/config.status $(top_srcdir)/scripts/python/module/PyNUT.py.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/Aix/nut.init: $(top_builddir)/config.status $(top_srcdir)/scripts/Aix/nut.init.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/HP-UX/postinstall: $(top_builddir)/config.status $(top_srcdir)/scripts/HP-UX/postinstall.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/ufw/nut.ufw.profile: $(top_builddir)/config.status $(top_srcdir)/scripts/ufw/nut.ufw.profile.in
scripts/python/app/NUT-Monitor-py2gtk2: $(top_builddir)/config.status $(top_srcdir)/scripts/python/app/NUT-Monitor-py2gtk2.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/python/app/NUT-Monitor-py3qt5: $(top_builddir)/config.status $(top_srcdir)/scripts/python/app/NUT-Monitor-py3qt5.in
cd $(top_builddir) && $(SHELL) ./config.status $@
scripts/python/module/test_nutclient.py: $(top_builddir)/config.status $(top_srcdir)/scripts/python/module/test_nutclient.py.in
cd $(top_builddir) && $(SHELL) ./config.status $@
mostlyclean-libtool:
@ -610,7 +729,10 @@ distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@ -675,7 +797,7 @@ distdir: $(DISTFILES)
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
@ -690,18 +812,22 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-zstd: distdir
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
@ -719,7 +845,7 @@ dist dist-all:
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \
@ -729,25 +855,27 @@ distcheck: dist
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_inst
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure \
&& $(am__cd) $(distdir)/_build/sub \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=.. --prefix="$$dc_install_base" \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
@ -816,14 +944,17 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
@ -832,7 +963,7 @@ distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-libtool \
distclean-tags
distclean-local distclean-tags
dvi: dvi-recursive
@ -876,7 +1007,8 @@ maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
maintainer-clean-am: distclean-am maintainer-clean-generic \
maintainer-clean-local
mostlyclean: mostlyclean-recursive
@ -898,22 +1030,32 @@ uninstall-am:
am--refresh check check-am clean clean-cscope clean-generic \
clean-libtool cscope cscopelist-am ctags ctags-am dist \
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
dist-xz dist-zip distcheck distclean distclean-generic \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am
dist-xz dist-zip dist-zstd distcheck distclean \
distclean-generic distclean-libtool distclean-local \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs installdirs-am \
maintainer-clean maintainer-clean-generic \
maintainer-clean-local mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am
.PRECIOUS: Makefile
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status libtool
distcheck-light:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_FLAGS)" distcheck
# Make a distcheck (and check in particular) with enabled valgrind and debug info
memcheck distcheck-valgrind:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_VALGRIND_FLAGS)" distcheck
# workaround the dist generated files that are also part of the distribution
# Note that distcleancheck is disabled for now, while waiting for a proper
# solution, that do not break older unix systems
@ -922,20 +1064,125 @@ distcheck-light:
distcleancheck:
@:
# Quick alias for root dir recipe:
realclean: maintainer-clean
# Executed after default rules
maintainer-clean-local:
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
# are included by generated Makefiles from other subdirectories, so they
# should be available during their clean-up). Just in case, we make sure
# here that their sub-distcleans complete first.
distclean-local:
@for DIR in $(SUBDIRS) ; do \
if test -f "$${DIR}/Makefile" ; then \
echo " DISTCLEAN in $${DIR}" >&2 ; \
( 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
# Hook the documentation building and validating recipes
# Note: these are optionally available (as determined during configure runs)
spellcheck spellcheck-interactive:
@RES=0; \
(cd $(builddir)/docs && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/docs/man && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/conf && $(MAKE) -s $@) || RES=$$? ; \
(cd $(builddir)/data && $(MAKE) -s $@) || RES=$$? ; \
exit $$RES
# Note: the "all-docs" and "check-docs" targets may require tools not
# found by `configure` script (and so avoided by conventional recipes)
# 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.
doc spellcheck-sortdict \
all-docs check-docs \
man all-man man-man check-man man-html all-html:
cd $(builddir)/docs && $(MAKE) $@
check-NIT check-NIT-devel:
cd $(builddir)/tests/NIT && $(MAKE) $@
# This target adds syntax-checking for committed shell script files,
# to avoid surprises and delays in finding fatal typos after packaging
###
### Note: currently, shellcheck target calls check-scripts-syntax
### so when both are invoked at once, in the end the check is only
### executed once. Later it is anticipated that shellcheck would
### be implemented by requiring, configuring and calling the tool
### named "shellcheck" for even more code inspection and details.
### Still, there remains value in also checking the script syntax
### by the very version of the shell interpreter that would run
### these scripts in production usage of the resulting packages.
###
check-scripts-syntax:
@echo 'NOTE: modern bash complains about scripts using backticks (warning not error), which we ignore in NUT codebase for portability reasons: `...` obsolete, use $$(...)'
@RUNBASH=bash; if [ -x /bin/bash ]; then RUNBASH=/bin/bash ; else if [ -x /usr/bin/env ] ; then RUNBASH="/usr/bin/env bash"; fi; fi ; \
for F in `git ls-files || find . -type f` ; do \
case "`file "$$F"`" in \
*"Bourne-Again shell script"*) ( set -x ; $$RUNBASH -n "$$F" ; ) ;; \
*"POSIX shell script"*|*"shell script"*) ( set -x ; /bin/sh -n "$$F" ; ) ;; \
esac || { RES=$$? ; echo "ERROR: Syntax check failed for script file: $$F" >&2 ; exit $$RES ; } ; \
done
@echo 'SUCCESS: Shell scripts syntax is acceptable, no fatal issues were found'
shellcheck-disclaimer:
@echo "==============================================================================="
@echo "NOTICE: 'make shellcheck' is currently an alias for 'make check-scripts-syntax'"
@echo "Later it may become a call to the real shellcheck tool (if available on the"
@echo "build system during the configure phase)"
@echo "==============================================================================="
# Note: currently not part of shellcheck target, because the script below
# can test the logic with numerous SHELL_PROGS in a CI setting, and because
# check-scripts-syntax probably has checked the basic syntax above already.
shellcheck-nde:
cd $(srcdir)/tests && SERVICE_FRAMEWORK="selftest" ./nut-driver-enumerator-test.sh
shellcheck: shellcheck-disclaimer check-scripts-syntax
@HAVE_CPPCHECK_TRUE@cppcheck: cppcheck-cxx11.xml cppcheck-c99.xml
# CPPCHECK_SRC_CXX += $(top_srcdir)/*.cpp $(top_srcdir)/*/*/*.cpp
@HAVE_CPPCHECK_TRUE@cppcheck-cxx11.xml: $(CPPCHECK_SRC_CXX) $(CPPCHECK_SRC_H)
@HAVE_CPPCHECK_TRUE@ $(CPPCHECK) --std=c++11 --enable=all --inconclusive --xml --xml-version=2 . 2>$@
@HAVE_CPPCHECK_TRUE@cppcheck-c99.xml: $(CPPCHECK_SRC_C) $(CPPCHECK_SRC_H)
@HAVE_CPPCHECK_TRUE@ $(CPPCHECK) --std=c99 --enable=all --inconclusive --xml --xml-version=2 . 2>$@
@HAVE_CPPCHECK_FALSE@cppcheck:
@HAVE_CPPCHECK_FALSE@ @echo "CPPCHECK analysis not available since 'cppcheck' was not found."
# Force ChangeLog regeneration upon make dist (due to nonexistant 'dummy-stamp'),
# in case it has already been generated previously
# Note that the script is hard-coded to generate "ChangeLog" in the current dir
dummy-stamp:
ChangeLog: tools/gitlog2changelog.py dummy-stamp
$(top_srcdir)/tools/gitlog2changelog.py $(GITLOG_START_POINT) || \
echo "gitlog2changelog.py failed to generate the ChangeLog. See https://github.com/networkupstools/nut/commits/master" > $@
cd $(top_builddir) && \
./tools/gitlog2changelog.py $(GITLOG_START_POINT) || \
{ echo "gitlog2changelog.py failed to generate the ChangeLog. See https://github.com/networkupstools/nut/commits/master" > $@ ; }
nut_version.h include/nut_version.h:
cd $(abs_top_builddir)/include && $(MAKE) nut_version.h
tools/gitlog2changelog.py: tools/gitlog2changelog.py.in
cd $(@D) && $(MAKE) -s $(@F)
# ----------------------------------------------------------------------
# Maintainers targets: distribution signature and hashes
dist-sig:
nut-@PACKAGE_VERSION@.tar.gz: dist
nut-@PACKAGE_VERSION@.tar.gz.sig: dist-sig
nut-@PACKAGE_VERSION@.tar.gz.md5 nut-@PACKAGE_VERSION@.tar.gz.sha256: dist-hash
dist-sig: nut-@PACKAGE_VERSION@.tar.gz
rm -f nut-@PACKAGE_VERSION@.tar.gz.sig
gpg --detach-sign nut-@PACKAGE_VERSION@.tar.gz
dist-hash:
dist-hash: nut-@PACKAGE_VERSION@.tar.gz
md5sum nut-@PACKAGE_VERSION@.tar.gz > nut-@PACKAGE_VERSION@.tar.gz.md5
sha256sum nut-@PACKAGE_VERSION@.tar.gz > nut-@PACKAGE_VERSION@.tar.gz.sha256
@ -971,7 +1218,7 @@ install-dirs:
@echo "Warning: 'make install-dirs' is deprecated."
@echo "Use 'make installdirs' instead."
@echo $(WARN)
make installdirs
$(MAKE) installdirs
cgi build-cgi install-cgi install-cgi-dir install-cgi-bin \
install-cgi-man install-cgi-conf install-cgi-html:
@echo "Error: 'make $@' no longer exists."
@ -987,26 +1234,52 @@ snmp build-snmp install-snmp install-snmp-mgr install-snmp-man:
@echo "Use './configure --with-snmp' instead."
setver:
@echo "Error: 'make setver' no longer exists."
@echo "Edit configure.in to set version number."
package:
if test `uname -s` = "HP-UX"; then \
cd scripts/HP-UX; \
make package; \
mv NUT_HPUX_package.depot NUT_HPUX_package@PACKAGE_VERSION@.depot; \
elif test `uname -s` = "SunOS"; then \
make; \
rm -rf @prefix@; \
make install; \
cd scripts/Solaris; \
make package; \
make uninstall; \
rm -rf @prefix@; \
elif test `uname -s` = "AIX"; then \
make dist; \
cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS; \
cp scripts/Aix/nut.init nut-*.tar.gz /usr/src/packages/SOURCES; \
rpm -ba /usr/src/packages/SPECS/nut-aix.spec; \
fi;
@echo "Edit configure.ac to set version number."
package: dist
DESTDIR="$(abs_builddir)/_install_pkgprotodir" ; export DESTDIR; \
rm -rf "$$DESTDIR"; \
case "`uname -s`" in \
"HP-UX") \
( cd scripts/HP-UX && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package && \
mv NUT_HPUX_package.depot $(abs_top_builddir)/NUT_HPUX_package@PACKAGE_VERSION@.depot ) ;; \
"SunOS") \
$(MAKE) $(AM_MAKEFLAGS) && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" install && \
( cd scripts/Solaris && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package ) && \
$(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" uninstall && \
rm -rf "$$DESTDIR" || \
{ echo "FAILED to produce SunOS packages, inspect '$$DESTDIR' for clues" >&2 ; exit 1; } ;; \
"AIX") \
if test -d /usr/src/packages/SPECS -a -w /usr/src/packages/SPECS ; then : ; else echo "Can not write to /usr/src/packages/SPECS" >&2 ; exit 1; fi ; \
if test -d /usr/src/packages/SOURCES -a -w /usr/src/packages/SOURCES ; then : ; else echo "Can not write to /usr/src/packages/SOURCES" >&2 ; exit 1; fi ; \
$(MAKE) $(AM_MAKEFLAGS) dist && \
cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS && \
cp scripts/Aix/nut.init nut-@PACKAGE_VERSION@.tar.gz /usr/src/packages/SOURCES && \
rpm -ba /usr/src/packages/SPECS/nut-aix.spec && \
mv /usr/src/packages/RPMS/nut*rpm $(abs_top_builddir)/ ;; \
*) echo "Unsupported OS for 'make $@' (no recipe bound)" >&2; exit 1;; \
esac
print-MAINTAINERCLEANFILES print-REALCLEANFILES:
@echo $(MAINTAINERCLEANFILES)
print-DISTCLEANFILES:
@echo $(DISTCLEANFILES)
# TODO: Recursive mode to consider patterns defined in sub-dir makefiles
git-realclean-check:
@if test -e .git && (command -v git); then \
git status --ignored || while read F ; do \
for P in $(MAINTAINERCLEANFILES) ; do \
case "$$F" in \
*/$$P) exit 1 ;; \
esac ; \
done; \
done ; \
fi
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

452
NEWS
View file

@ -1,7 +1,413 @@
If you're upgrading from an earlier version, see the UPGRADING file.
For a complete and more detailed list of changes, please refer to the
ChangeLog file.
ChangeLog file (generated for release archives), or to the Git version
control history for "live" codebase.
---------------------------------------------------------------------------
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.
- New (optional) keywords for configuration files were added,
so existing NUT 2.7.x builds would not accept them if some
deployments switch versions back and forth -- due to this,
semantically the version was bumped to NUT 2.8.x.
- Add support for openssl-1.1.0 (Arjen de Korte)
- libusb-1.0 API support in addition to libusb-0.1 API [#300]
- Add support for `DISABLE_WEAK_SSL=true` in upsd.conf to disable older/weaker
SSL/TLS protocols and ciphers: when NUT is built against relatively recent
versions of OpenSSL or NSS it will be restricted to TLSv1.2 or better.
For least-surprise, currently defaults to `false` and complains in log
[PR #1043]
- Add support for `ALLOW_NO_DEVICE=true` (as an upsd.conf flag or environment
variable passed from caller of the program), to allow starting the data
server initially without any device configurations and reloading it later
to apply config changes on the fly [PR #766]
- Add support for `debug_min=NUM` setting (ups.conf, upsd.conf, upsmon.conf)
to specify the minimum debug verbosity for daemons. This allows "in-vivo"
troubleshooting of service daemons without editing init scripts or service
unit definitions.
- Improve support for upsdrvctl for managing of numerous device configs,
including default "maxretry=3" and a "nowait" option to complete the
"start of everything" mode after triggering the drivers and not waiting
for them to complete initializing. This matters on systems that monitor
from dozens to hundreds of devices.
- Drivers support a new value for `synchronous` setting, which is the
new default now: `auto`. Initially after driver start-up this mode
acts as the older default `off`, but would fall back to `on` in case
the driver fails to send reports to `upsd` by overflowing the socket
buffer in async mode -- so the next connections of this driver uptime
would be synchronized (potentially slower, but safer -- blocking on
writes to the data server). This adaptation would primarily impact
and benefit devices with many (hundreds of) data points, such as
ePDUs and daisy chains. [issue #1309, PR #1315]
- Daemons such as upsd, upsmon, upslog, and device drivers previously
implied that enabled debugging (or upslog to stdout) means foreground
running, otherwise the daemon was always sent to the background.
Now there are explicit options for this (`-F`/`-B`), although default
behavior is retained. This change is used for simplified service unit
definitions.
- Improvements for device discovery or driver "lock-picking", including
general support for:
* "Standalone" mode (`-s` option), to monitor a device which is not
detailed or mentioned in ups.conf
* `NUT_ALTPIDPATH` and `NUT_STATEPATH` environment variables to override
the paths built into the driver binary [PR #473 and #507]
* "Driver data dump" mode (`-d` option), to poll a device for one or
few ('update_count' ) loops, report discovered values (dump the data
tree in upsc-like format), and exit. This complements the `nut-scanner`
for finding and identifying devices.
- support for new devices:
* IBM 6000 VA LCD 4U Rack UPS; 5396-1Kx (USB)
* Phoenix Contact QUINT-UPS model 2320461 (Modbus)
* Tripp-Lite SU3000LCD2UHV (USB; protocol 1330)
* Emerson Avocent PM3000 PDU (SNMP)
* HPE ePDU (SNMP)
- nutdrv_qx: enhanced estimation of remaining battery runtime based
on speed of voltage drop, which varies as they age [PR #1027]
- nutdrv_qx: several subdrivers added or improved, including:
* "snr" subdriver with USB connection, for SNR-UPS-LID-XXXX [PR #1008].
Note that end-users should reference explicitly the `snr` subdriver
in their `ups.conf` settings because of USB chip using the same
values of VendorID/ProductID as fabula_subdriver, fuji_subdriver,
and krauler_subdriver.
* "hunnox" subdriver, as a dialect of earlier "fabula" [PR #638]
adds support for Hunnox HNX-850 with USB connection and reported to work
for Powercool, Iron Guardian, ARES devices and possibly many others from
discussions linking to the pull request which introduced the driver.
* "phoenixtec" subdriver for Masterguard A and E series, device series
A700/1000/2000/3000(-19) and E40/60/100(-19). [PR #975]
* "ablerex" subdriver provided by the OEM vendor, note that it replaces
"krauler_subdriver" as default handler for VID:PID 0xffff:0x0000
[PR #1135]
* Legrand HID defined and handled by "krauler_subdriver" by default
[PR #1075, issue #616]
* add new "armac" subdriver, tested with Armac R/2000I/PSW, but should
support other UPSes that work with "PowerManagerII" software from
Richcomm Technologies from around 2004-2005 [PR #1239, issue #1238]
- microsol-apc (starting at version 0.68 as derived from solis 0.67):
adding support for newer APC Back-UPS BR hardware, such as
APC Back-UPS BZ1500, BZ2200BI and BZ2200I [PR #994]
- pijuice: added new i2c bus driver for PiJuice HAT, a battery UPS module
for the Raspberry Pi systems [PR #730]
- huawei-ups2000: added new driver for USB (Linux 5.12+ so far) and Serial
RS-232 Modbus device support of Huawei UPS2000/2000A (1kVA-3kVA) series,
and possibly some related FSP UPS models. [PR #954]
- socomec_jbus: added new driver for modbus-based JBUS protocol over serial
RS-232 for Socomec UPS (tested with a DIGYS 3/3 15kVA model, working
on Linux x86-64 and Raspberry Pi 3 ARM). [PR #1313]
- adelsystem_cbi: added new driver for ADELSYSTEM CBI2801224A, an all-in-one
12/24Vdc DC-UPS, which supports the modbus RTU communication protocol
[PR #1282]
- generic_modbus: added new driver for TCP and Serial Modbus device support.
The driver has been tested against PULS UPS (model UB40.241) via
MOXA ioLogikR1212 (RS485) and ioLogikE1212 (TCP/IP), and configuration
allows to map custom registers and addresses to NUT events [PR #1052]
- genericups: added support for FTTx battery backup devices, and new signal
type mappings for the contact closure pins interpretation (RB for replace
battery, BYPASS for disconnected battery, and "none" or NULL for signals
to ignore) [PR #1061]
- add devices to HCL/DDL:
* APC Back-UPS CS (USB)
* CPS CP1500EPFCLCD (USB)
* CPS EC350G, EC750G (USB)
* CPS PR2200LCDRT2U (SNMP)
* Eaton ATS 16 and 30 (SNMP)
* Eaton 5E2200VA (USB)
* Eaton 9PX Split Phase 6/8/10 kVA (XML/USB/SHUT)
* Eaton 9PX (XML/USB/SHUT)
* Eaton Ellipse PRO 650 VA (USB)
* Ippon Back Comfo Pro II 650/850/1050 (USB)
* Numeric Digital 800 (USB)
* Opti-UPS PS1500E (USB)
* Powercool 350VA to 1600VA (USB)
- C++11 support in nutclient library and cppunit tests
- Added C++ testing mock for TcpClient class (nutclientmem/MemClientStub:
data stored in local memory) [PR #1034]
- Dual Python 2 and 3 compatibility in development scripts; ability to
run build activities and resulting built NUT programs on systems that
do not have a binary named "python" [PR #1115 and some before it]
- Added Russian translation for NUT-Monitor GUI client [PR #806]
- Separated NUT-Monitor UI into two applications, NUT-Monitor-py2gtk2 and
NUT-Monitor-py3qt5, suitable for two generations of Python ecosystem
with their great differences; `NUT-Monitor` name is retained for wrapper
script which calls one of these, such that the current system can execute
[PRs #1310, #1354]
- Various USB driver families: expanded device-matching with "device" in
addition to "bus" and generic USB fields. This is needed to support
multiple attached devices that seem identical by other fields (e.g.
same vendor, same model, same USB bus, and no serial number) [PR #974]
- Various USB driver families: Improved HID parsing for byte-stream to
number conversions on different CPU architectures [PR #1024]
- Various USB HID driver families: added support for composite devices
utilizing interface greater than 0 for the UPS interface [PR #1044]
- usbhid-ups:
* added generic framework for fixing Report Descriptors which can be
used for different manufacturers by adding code to the appropriate
subdriver rather than polluting the main code with UPS specific
exceptions, and applied fixes for known mistakes in (some releases
of firmware for) CyberPower CPS*EPFCLCD [issue #439, PR #1245]
* added `onlinedischarge` option for UPSes that report `OL+DISCHRG`
when wall power is lost [PR #811]
* changed detection of VendorID 0x06da handling of which is claimed
by Liebert/Phoenixtec HID historically, and MGE HID (for AEG PROTECT
NAS UPSes) since NUT 2.7.4, so that the higher-priority MGE subdriver
would not grab each and all of the devices exposing that ID [PR #1357]
* CPS HID: add input.frequency and output.frequency
* OpenUPS2: only check OEM Information string once (fewer log messages)
* Liebert GXT4 USB VID:PID [10AF:0000]
* add battery voltage and input/output transfer voltage and frequency
in Liebert/Phoenixtec HID mapping, to support PowerWalker VFI 2000 TGS
better [PR #564, issue #560]
* add a little delay between multicommands [PR #1228]
* fix Eaton/MGE mapping for beeper handling
* add IBM USB VID
* add deep battery test for CyberPower OL3000RMXL2U
* report the libusb version used
* fixed CPU architecture dependent bitmask math issues, causing wrong
numbers interpreted from wire protocol data in Big-Endian LP64 builds
(SPARC64, s390x, etc.) [issue #1023, PRs #1024, #1040, #1055, #1226]
* add Delta UPS Amplon R Series, tested on R1K and R3K model [PR #987]
* add Delta Minuteman UPS VID/PID [PR #1230, issues #555 and #1227]
* add AMETEK Powervar UPM [PR #733]
* add Tripplite AVR750U (ProductID 0x3024) [PR #963]
* add Arduino HID device support with new arduino-hid subdriver [PR #1044]
* add new salicru-hid subdriver, tested with Salicru SPS Home 850 VA
[PR #1199, issue #732]
* add new ever-hid subdriver to support EVER UPS devices (Sinline RT Series,
Sinline RT XL Series, ECO PRO AVR CDS Series) [PR #431]
* add ability to set `battery.mfr.date` for APC HID UPS [PR #1318]
- usbhid-ups / mge-shut: compute a realpower output load approximation for
Eaton UPS when the needed data is not present
- snmp-ups:
* APC ePDU MIB support
* add `input.phase.shift` variable
* add configurable write-able `ondelay` (`ups.delay.start`) and `offdelay`
(`ups.delay.shutdown`) as timeticks support [PR #276]
* outlet groups
* fix the rounding / truncation of some values
* add outlet.N.name for Eaton ePDU
* add input.bypass.frequency for Eaton 3ph
* fix support for Eaton 2-phase ("split phase") UPS
* add flag to list currently loaded MIB-to-NUT mappings
* fix input.L2.voltage on Eaton G2/G3 PDU
* update Eaton Aphel Revelation MIB
* support Raritan Dominion PX2 PDU
* support Emerson Avocent PM3000 PDU
* improve ALARM flag handling
* add firmware version for new HPE Network card
* add ups.load, battery.charge, input.{voltage,frequency} and output.voltage
for CyberPower, as well as shutdown and other instant commands
* several rounds of updates for Eaton devices, including new ATS and ePDU
hardware families
* fixed bit mask values for flags to surely use different numbers behind
logical items (inevitably changing some of those macro symbols) [PR #1180]
- snmp-ups and nut-scanner should now support more SNMPv3 Auth and Priv
protocols, as available at NUT build time [PRs #1165, #1172]
- nut-scanner: various improvements, including:
* detection of libraries at runtime
* tracing information
* limiting parallelism (thread count) [PRs #1158, #1164]
- nut-ipmipsu: improve FreeIPMI support to build cleanly against older and
newer FreeIPMI versions [PR #1179]
- the powerpanel driver now also supports CyberPower OR1500LCDRTXL2U with
serial cable [PR #538]
- powercom driver: implement `nobt` config parameter to skip battery check
on initialization/startup [PR #1256]
- netxml-ups:
* Report calibration status
* Fix for erroneous battery info (MGEXML/0.30) [PR #1069]
- solis: various improvements and fixes
- liebert-esp2: Correct battery V scaling, update docs, implement split-phase
unit support [PR #412]
- tripplite: the "Tripp-Lite SmartUPS driver" as tested with SMART2200NET
learned to discover the firmware generation and some device features,
and in particular to manage power separately on one or two outlet groups
[PR #1048]
- tripplite_usb: updated to recognize the "3005" protocol [PR #584]
- libnutclient: introduce getDevicesVariableValues() to improve performances
when querying many devices (up to 15 times faster)
- nut-driver-enumerator: introduced a script for Linux systemd and
Solaris/illumos SMF to inspect current NUT configuration in ups.conf
file and generate service management instances for each currently
tracked power device. Also introduced services to monitor the NUT
configuration and react to editions of this file, mostly intended
for deployments that do massive monitoring of dynamically changing
farms of power devices.
- Fix File descriptors leaks by upsmon and upssched (SELinux errors)
- systemd support improvements:
* POWEROFF_WAIT
* reload support for upsd
* Deliver systemd-tmpfiles config to pre-create runtime locations
[PR #1037 for Issue #1030]
* Update units with SyslogIdentifier=%N for better logging [PR #1054]
- upsrw: display the variable type beside ENUM / RANGE
- Added `PROTVER` as alias to `NETVER` to report the protocol version in use.
Note that NUT codebase itself does not use this value and handles commands
and reported errors individually [issue #1347]
- Implement status tracking for instant commands (instcmd) and variables
settings (setvar): this allows to get the actual execution status from the
driver, and is available in libraries and upscmd / upsrw [PR #659]
- Add support for extra parameter for instant commands, both in library and
in upscmd
- 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)
vs. `dummy-loop` (legacy default for `*.seq` and others) [issue #1385]
- new protocol variables:
* `input.phase.shift`
* `outlet.N.name`
* `outlet.N.type`
* `battery.voltage.cell.max`, `battery.voltage.cell.min`
* `battery.temperature.cell.max`, `battery.temperature.cell.min`
* `battery.status`
* `battery.capacity.nominal`
* `battery.date.maintenance` (and clarified purpose of `battery.date`)
* `battery.packs.external` (and clarified purpose of `battery.packs`)
* `experimental.*` namespace introduced [PR #1046] to facilitate
introduction of NUT drivers and their data points for which we do
not yet have concepts, or which the original driver contributors
did not map well per suitable NUT standards: this allows to balance
having those drivers available in the project vs. least surprise
for when the explicitly experimental names are changed to something
stable and standardized.
* Proposed to track Date and Time values (still as "opaque strings")
preferably in representations compatible to ISO-8601/RFC-3339 [PR #1076]
(standards update; changes to actual codebase to be applied in the future)
** New routine to convert a US formatted date string "MM/DD/YYYY" to an
ISO 8601 Calendar date "YYYY-MM-DD" was added to snmp-ups.c [PR #1078]
- Master/Slave terminology was deprecated in favor of Primary/Secondary
modes of `upsmon` client:
* Respective keywords in the configuration files (`upsd.users` and
`upsmon.conf`) are supported as backwards-compatible settings,
but the obsoleted values are no longer documented.
* Protocol keyword support was similarly updated, with `upsmon` now
first trying to elevate privileges with `PRIMARY <ups>` request,
and falling back to `MASTER <ups>` just in case it talks to an
older build of an `upsd` server.
* For the principle of least surprise, NUT codebase still exposes the
`net_master()` (as handler for `MASTER` net command) in header and
C code for the sake of existing linked binaries, and returns the
`OK MASTER-GRANTED` line to the older client that invoked it.
* Newly introduced `net_primary()` (as handler for `PRIMARY` net command)
calls the exact same application logic, but returns `OK PRIMARY-GRANTED`
line to the client.
* Python binding updated to handle both cases, as the only found in-tree
protocol consumer of the full-line text.
* For more details see issue #840 and several pull requests referenced
from it, and discussions on NUT mailing lists.
- Build fixes:
* In general, numerous fixes were applied to ensure portability and avoid
warnings (fixing a number of real bugs that caused them); CI was extended
to keep the codebase free of those types of warnings which we have got
rid of, requiring builds to succeed cleanly in several dozen combinations
of compiler versions, C standard revisions (C99 upwards, though on many
OSes with GNU99+ extensions), operating systems and CPU architectures.
* Public CI introduced to automatically test every contribution (PR) and
resulting increment of main NUT codebase, including Travis CI and LGTM.com
services, and a Jenkins farm on virtual hardware donated by Fosshost.org;
this augments testing earlier provided for some branches by Buildbot.
* Added cppunit testing with valgrind for the C++ client library
* Make targets added for shell script syntax checks for helper and service
scripts
* Make targets added for spellcheck and for maintenance of the dictionary,
including incremental spellcheck to only parse recently edited text files
* The AsciiDoc detection has been reworked to allow NUT to be built from
source without requiring asciidoc/a2x (using pre-built man pages from
the distribution tarball, for instance)
* Makefile contents rearranged for more resilient out-of-tree and in-tree
builds beside those made from the root workspace directory
* Makefiles are tested with GNU Make and BSD Make to ensure portable recipes
* More use of `pkg-config` to detect dependencies at configure time, as
well as fail-safe detection of presence of pkg-config (and its macros)
to survive and build without it too
* "slibtool" pedantic nuances now supported, allowing an alternative to
GNU libtool
* Build scripts updated to remove obsoleted calls to cleanly work with
autoconf-2.70 releases in 2020 (also works with 2.69 which was the
earlier release since 2012)
* Dynamic library loading used in certain programs and use-cases improved,
especially for 64-bit vs 32-bit builds on multiple-bitness OSes
* Logging routines like `upsdebugx()` were refactored as macros so there
is slightly less overhead when logging is disabled [PRs #685 and #1100]
* Numerous classes of compilation warnings eradicated, many of those being
potential issues with implicit data type conversions and varied numeric
type width, signedness, string buffer size, uninitialized variables or
structure fields; some more in progress
* Several logical errors found and fixed during this walk over codebase.
* Cases where compilers were overly zealous and particular code was written
the way wit was intentionally, including some comparisons that help with
different-bitness builds but indeed seem superfluous in a certain single
bitness, were commented and encased in pragmas to disable the warnings
* Basic coding style (indentations, lack of trailing white space) applied
per developer guide, but not automatically enforced/checked yet.
- Due to changes needed to resolve build warnings, mostly about mismatching
data types for some variables, some structure definitions and API signatures
of several routines had to be changed for argument types, return types,
or both. Primarily this change concerns internal implementation details
(may impact update of NUT forks with custom drivers using those), but a
few changes also happened in header files installed for builds configured
`--with-dev` and so may impact `upsclient` and `nutclient` (C++) consumers.
At the very least, binaries for those consumers should be rebuilt to remain
stable with NUT 2.8.0 and not mismatch int-type sizes and other arguments.
- 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:
@ -374,7 +780,7 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3:
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 Ascii charset from
Thus, fix NUT parser, to only allow the subset of ASCII charset from
Space to ~
(Reported by Sebastian Pohle, Alioth bug #313636, CVE-2012-2944)
@ -436,7 +842,7 @@ Release notes for NUT 2.6.4 - what's new since 2.6.3:
- 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
improved, to prepare for superseeding bestups driver
improved, to prepare for superseding bestups driver
- bestups has also received some care, though users are encouraged to switch
to blazer_ser, since bestups will soon be deprecated.
@ -527,7 +933,7 @@ Release notes for NUT 2.6.3 - what's new since 2.6.2:
- Base files for HPUX packaging have been added. This is still a work in
progress.
- Compilation on IBM Aix has been fixed (namespace conflict with ctypes).
- Compilation on IBM AIX has been fixed (namespace conflict with ctypes).
- more bugfixes, cleanup and improvements, on both source code and
documentation.
@ -565,7 +971,7 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1:
along with Java archives (.jar) in the Download section.
- support for new devices: Eaton 3S ; Cyber Power Systems CP1000AVRLCD ;
various APC models equiped with APC AP9618 management card, including APC
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).
@ -590,9 +996,9 @@ Release notes for NUT 2.6.2 - what's new since 2.6.1:
the default 3 seconds.
- snmp-ups.c has a new initialization method, that uses sysObjectID, which is
a pointer to the prefered MIB of the device, to detect supported devices.
a pointer to the preferred MIB of the device, to detect supported devices.
This speeds up even more init stage and should render void the use of 'mib'
option. SNMP v3 session initialisation has also been fixed, and Eaton PDU
option. SNMP v3 session initialization has also been fixed, and Eaton PDU
support has been completed.
- Initial support has been added for systemd, the System and Service Manager
@ -635,9 +1041,9 @@ Release notes for NUT 2.6.1 - what's new since 2.6.0:
- usbhid-ups has completed a bit supported variables for APC and Eaton / MGE.
- on the quality assurance side, Eaton has worked on fixing a few non
conformances, like C++ style comments and warnings, using a newly developed
verification tool (Prachi Gandhi).
- on the quality assurance side, Eaton has worked on fixing a few
non-conformance issues, like C++ style comments and warnings, using
a newly developed verification tool (Prachi Gandhi).
- fix remaining references to LIBSSL_LDFLAGS, instead of LIBSSL_LIBS,
which cause unresolved symbol on libupsclient users (Fabrice Coutadeur).
@ -696,7 +1102,7 @@ Release notes for NUT 2.6.0 - what's new since 2.4.3:
- improve configure time dependencies checking and processing.
- improve older Unix systems support (HP-UX, Aix, ...) for missing functions.
- improve older Unix systems support (HP-UX, AIX, ...) for missing functions.
- refresh and improve USB helper files (udev and UPower).
@ -767,7 +1173,7 @@ Release notes for NUT 2.4.1 - what's new since 2.4.0:
version 1.1.
- the situation of the build toolchain has been fixed, with regard to the
"make clean" target and the wrongly removed generated USB files. This brokes
"make clean" target and the wrongly removed generated USB files. This broke
further configure call.
---------------------------------------------------------------------------
@ -810,7 +1216,7 @@ Release notes for NUT 2.4.0 - what's new since 2.2.2:
- NUT now ships a bash completion function for 'upsc' command
(scripts/misc/nut.bash_completion). Simply copy it to /etc/bash_completion.d
- many internal changes to improve maintenability, while lowering the
- many internal changes to improve maintainability, while lowering the
maintenance cost (thus allowing developers to focus on what matters: the
code!). Examples of this are:
- the USB information automatic extraction to generate the various USB helper
@ -926,7 +1332,7 @@ 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
synchronisation release, though it includes many bugfixes and support
synchronization release, though it includes many bugfixes and support
for new models.
- support for new devices: APC Smart-UPS with 6TI firmware; Belkin
@ -960,12 +1366,12 @@ 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 buxfixes and new models support and
also received some more care, like bugfixes and new models support and
enhancement for Solaris.
[Peter Selinger and Arnaud Quette]
- A bug has been fixed in NUT core to support resuming from suspend-to-disk.
This should also fix other similar issues, like time synchronisation
This should also fix other similar issues, like time synchronization
through the NTP - Network Time Protocol.
[Arjen de Korte]
@ -988,7 +1394,7 @@ Release notes for NUT 2.0.4 - what's new since 2.0.3:
[Carlos Rodrigues]
- The new rhino driver was added to support Microsol Rhino UPS hardware
The solis has also been improved for solaris compatibility, and
The solis has also been improved for Solaris compatibility, and
internal / external shutdown programming. solis can now save external
shutdown programming to ups, and support new cables for solis 3
[Silvino B. Magalhães]
@ -1028,7 +1434,7 @@ Release notes for NUT 2.0.3 - what's new since 2.0.2:
ups.model retrieval for some specific case (release 0.65)
- The drivers don't change to the "statepath" directory anymore at
initialisation time if called using -k. This avoid unneeded
initialization time if called using -k. This avoid unneeded
failure to poweroff the UPS if /var is already unmounted.
[Gaspar Bakos]
@ -1048,7 +1454,7 @@ Release notes for NUT 2.0.3 - what's new since 2.0.2:
- The packaging files for Red Hat have received various fixes
[Thomas Jarosch]
- The solis driver has been fixed to avoid a naming colision and
- The solis driver has been fixed to avoid a naming collision and
compile on Solaris
[Paweł Kierdelewicz]
@ -1090,7 +1496,7 @@ Release notes for NUT 2.0.2 - what's new since 2.0.1:
[Thanos Chatziathanassiou, Olli Salvia]
- The bcmxcp driver is back with support for Powerware UPSs.
[Tore Øpetveit, Kjell Claesson]
[Tore Ørpetveit, Kjell Claesson]
- The cyberpower driver now supports CyberPower 1000AVR.
[Dave Huang]
@ -1101,7 +1507,7 @@ Release notes for NUT 2.0.2 - what's new since 2.0.1:
- The apcsmart driver has fixed APC600 support.
- The etapro driver fixes brokeness due to ser_get_line use
- The etapro driver fixes brokenness due to ser_get_line use
[Marek Michalkiewicz]
- The new upscode2 driver supports Fiskars, Compaq and Powerware
@ -1153,7 +1559,7 @@ Release notes for NUT 2.0.1 - what's new since 2.0.0:
and bypass control.
[Gert Lynge]
- The tripplite driver has recieved a major overhaul to bring it up to
- The tripplite driver has received a major overhaul to bring it up to
working condition for the 2.0 tree, including code cleanups, several
new variables, commands, and user-definable parameters. See
ChangeLog for more.
@ -1312,7 +1718,7 @@ Release notes for NUT 2.0.0 - what's new since 1.4.x:
instcmds.
- Effekta MT 2000 RM hardware is now supported by the fentonups driver.
[christoph moar]
[Christoph Moar]
- The new safenet driver supports UPS hardware that uses the protocol
of the same name. This includes models from many manufacturers,

76
README
View file

@ -120,8 +120,9 @@ The entry in `ups.conf` looks like this:
driver = apcsmart
port = /dev/ttyS1
To start and stop drivers, use upsdrvctl. By default, it will start or
stop every UPS in the config file:
To start and stop drivers, use upsdrvctl of upsdrvsvcctl (installed on
operating systems with a service management framework supported by NUT).
By default, it will start or stop every UPS in the config file:
/usr/local/ups/sbin/upsdrvctl start
/usr/local/ups/sbin/upsdrvctl stop
@ -131,6 +132,17 @@ However, you can also just start or stop one by adding its name:
/usr/local/ups/sbin/upsdrvctl start sparky
/usr/local/ups/sbin/upsdrvctl stop sparky
On operating systems with a supported service management framework,
you might wrap your NUT drivers into individual services instances
with:
/usr/local/ups/sbin/upsdrvsvcctl resync
and then manage those service instances with commands like:
/usr/local/ups/sbin/upsdrvsvcctl start sparky
/usr/local/ups/sbin/upsdrvsvcctl stop sparky
To find the driver name for your device, refer to the section below
called "HARDWARE SUPPORT TABLE".
@ -236,7 +248,7 @@ Power distribution unit management
NUT also provides an advanced support for power distribution units.
You should read the <<Outlets_PDU_notes,Configuring automatic UPS shutdowns>>
You should read the <<outlet_management,NUT outlets management and PDU notes>>
chapter to learn more about when to use this feature.
Network Server
@ -261,32 +273,52 @@ separate section in the documentation since it is so important.
You configure it by telling it about UPSes that you want to monitor in
upsmon.conf. Each UPS can be defined as one of two possible types:
a "primary" or "secondary".
Master
~~~~~~
Primary
~~~~~~~
This UPS supplies power to the system running `upsmon`, and this system is also
responsible for shutting it down when the battery is depleted. This occurs
after any slave systems have disconnected safely.
The monitored UPS possibly supplies power to this system running `upsmon`,
but more importantly -- this system can manage the UPS (typically, this
instance of `upsmon` runs on the same system as the `upsd` and driver(s)):
it is capable and responsible for shutting it down when the battery is
depleted (or in another approach, lingering to deplete it or to tell the
UPS to reboot its load after too much time has elapsed and this system
is still alive -- meaning wall power returned at a "wrong" moment).
If your UPS is plugged directly into a system's serial port, the `upsmon`
process on that system should define that UPS as a master.
The shutdown of this (primary) system itself, as well as eventually an
UPS shutdown, occurs after any secondary systems ordered to shut down
first have disconnected, or a critical urgency threshold was passed.
If your UPS is plugged directly into a system's serial or USB port, the
`upsmon` process on that system should define its relation to that UPS
as a primary. It may be more complicated for higher-end UPSes with a
shared network management capability (typically via SNMP) or several
serial/USB ports that can be used simultaneously, and depends on what
vendors and drivers implement. Setups with several competing primaries
(for redundancy) are technically possible, if each one runs its own
full stack of NUT, but results can be random (currently NUT does not
provide a way to coordinate several entities managing the same device).
For a typical home user, there's one computer connected to one UPS.
That means you run a driver, `upsd`, and `upsmon` in master mode.
That means you would run on the same computer the whole NUT stack --
a suitable driver, `upsd`, and `upsmon` in primary mode.
Slave
~~~~~
Secondary
~~~~~~~~~
This UPS may supply power to the system running `upsmon`, but this system can't
shut it down directly.
The monitored UPS may supply power to the system running `upsmon` (or
alternatively, it may be a monitoring station with zero PSUs fed by
that UPS), but more importantly, this system can't manage the UPS --
e.g. shut it down directly (through a locally running NUT driver).
Use this mode when you run multiple computers on the same UPS. Obviously, only
one can be connected to the serial port on the UPS, and that system is the
master. Everything else is a slave.
Use this mode when you run multiple computers on the same UPS.
Obviously, only one can be connected to the serial or USB port
on a typical UPS, and that system is the primary. Everything
else is a secondary.
For a typical home user, there's one computer connected to one UPS.
That means you run a driver, upsd, and upsmon in master mode.
That means you run a driver, `upsd`, and `upsmon` in primary mode.
Additional Information
~~~~~~~~~~~~~~~~~~~~~~
@ -476,7 +508,11 @@ 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 Subversion) and snapshots. Since 2.7 line of releases,
sources are tracked in Git revision control system, with the project
ecosystem being hosted on GitHub, and improvements or other contributions
merged through common pull request approach and custom NUT CI testing
on multiple platforms.
Major release jumps are mostly due to large changes to the features
list. There have also been a number of architectural changes which

4
TODO
View file

@ -13,7 +13,7 @@ Roadmap
^^^
This release is focused on the website and documentation rewrite, using
the excellent link:http://www.methods.co.nz/asciidoc[AsciiDoc].
the excellent link:https://asciidoc.org/[AsciiDoc].
2.8
^^^
@ -113,6 +113,6 @@ and https://alioth.debian.org/tracker/?atid=411545&group_id=30602&func=browse[fe
solar panel driver, and the powerman internal approach of a generic engine with
a scripting interface is a cool idea.
Ref http://powerman.svn.sourceforge.net/viewvc/powerman/trunk/etc/apcpdu.dev?revision=969&view=markup
- integrate the (future) new powerman LUA engine (maybe/mustbe used for the driver above?)
- integrate the (future) new powerman LUA engine (maybe/must-be used for the driver above?)
for native PDU support
- see how we can help and collaborate with DeviceKit-power

130
UPGRADING
View file

@ -7,6 +7,132 @@ 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.
Changes from 2.7.4 to 2.8.0
---------------------------
- Note to distribution packagers: this version hopefully learns from many
past mistakes, so many custom patches may be no longer needed. If some
remain, please consider making pull requests for upstream NUT codebase
to share the fixes consistently across the ecosystem. Also note that
some new types of drivers (so package groups with unique dependencies)
could have appeared since your packaging was written (e.g. with modbus),
as well as new features in systemd integration (`nut-driver@instances`
and the `nut-driver-enumerator` to manage their population), as well as
updated Python 2 and Python 3 support (again, maybe dictating different
package groups) as detailed below.
- Due to changes needed to resolve build warnings, mostly about mismatching
data types for some variables, some structure definitions and API signatures
of several routines had to be changed for argument types, return types,
or both. Primarily this change concerns internal implementation details
(may impact update of NUT forks with custom drivers using those), but a
few changes also happened in header files installed for builds configured
`--with-dev` and so may impact `upsclient` and `nutclient` (C++) consumers.
At the very least, binaries for those consumers should be rebuilt to remain
stable with NUT 2.8.0 and not mismatch int-type sizes and other arguments.
- libusb-1.0: NUT now defaults to building against libusb-1.0 API version
if the configure script finds the development headers, falling back to
libusb-0.1 if not. Please report any regressions.
- apcupsd-ups: When monitoring a remote apcupsd server, interpret "SHUTTING
DOWN" as a NUT "LB" status. If you were relying on the previous behavior
(for instance, in a monitor-only situation), please adjust your upsmon
settings. Reference: https://github.com/networkupstools/nut/issues/460
- Packagers: the AsciiDoc detection has been reworked to allow NUT to be built
from source without requiring asciidoc/a2x (using pre-built man pages from
the distribution tarball, for instance). Please double-check that we did not
break anything (see docs/configure.txt for options).
- Driver core: options added for standalone mode (scanning for devices without
requiring ups.conf) - see docs/man/nutupsdrv.txt for details.
- oldmge-shut has been removed, and replaced by mge-shut.
- New drivers for devices with "Qx" (also known as "Megatec Q*") family of
protocols should be developed as sub-drivers in the `nutdrv_qx` framework
for USB and Serial connected devices, not as updates/clones of older e.g.
`blazer` family and `bestups`. Sources, man pages and start-up messages
of such older drivers were marked with "OBSOLETION WARNING".
- liebert-esp2: some multi-phase variable names have been updated to match the
rest of NUT.
- netxml-ups: if you have old firmware, or were relying on values being off by
a factor of 10, consider the `do_convert_deci` flag. See
docs/man/netxml-ups.txt for details.
- snmp-ups: detection of Net-SNMP has been updated to use `pkg-config` by
default (if present), rather than `net-snmp-config(-32|-64)` script(s) as
the only option available previously. The scripts tend to specify a lot
of options (sometimes platform-specific) in suggested `CFLAGS` and `LIBS`
compared to the packaged `pkg-config` information which also works and is
more portable. If this change bites your distribution, please bring it up
in https://github.com/networkupstools/nut/issues or better yet, post a PR.
Also note that `./configure --with-netsnmp-config(=yes)` should set up the
preference of the detected script over `pkg-config` information, if both
are available, and `--with-netsnmp-config=/path/name` would as well.
- snmp-ups: bit mask values for flags in earlier codebase were defined in a
way that caused logically different items to have same numeric values.
This was fixed to surely use different definitions (so changing numbers
behind some of those macro symbols), and testing with UPS, ePDU and ATS
hardware which was available did not expose any practical differences.
- usbhid-ups: numeric data conversion from wire protocol to CPU representation
in GetValue() was completely reworked, aiming to be correct on all CPU types.
That said, regressions are possible and feedback is welcome.
- nut-scanner: Packagers, take note of the changes to the library
search code in common/common.c. Please file an issue if this does not work
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)
vs. `dummy-loop` (legacy default for `*.seq` and others) [issue #1385]
* Note this can break third-party test scripts which expected `*.dev`
files to work as a looping sequence with a `TIMER` keywords to change
values slowly; now such files should get processed to the end once.
Specify `mode=dummy-loop` driver option or rename the data file used
in the `port` option for legacy behavior.
Use/Test-cases which modified such files content externally should
not be impacted.
- Python: scripts have been updated to work with Python 3 as well as 2.
* PyNUT module (protocol binding) supports both Python generations.
* NUT-Monitor (desktop UI client) got separated into two projects:
one with support for Python2 and GTK2, and another for Python3 and Qt5.
On operating systems that serve both environments, either of these
implementation should be usable. For distributions that deprecated
and removed Python2 support, it is a point to consider in NUT packages
and their build-time and installation dependencies.
The historic filenames for desktop integration (`NUT-Monitor` script
and `nut-monitor.desktop`) are still delivered, but now cover a wrapper
script which detects the environment capabilities and launches the best
suitable UI implementation (if both are available).
- apcsmart: updates to CS "hack" (see docs/man/apcsmart.txt for details)
- upsdebugx(): added `[D#]` prefix to log entries with level > 0
so if any scripts or other tools relied on parsing those messages
making some assumptions, they should be updated
- upsdebugx() and related methods are now macros, optionally calling similarly
named implementations like s_upsdebugx() as a slight optimization; this may
show up in linking of binaries for some customized build scenarios
- libraries, tools and protocol now support a `TRACKING` ID to be used with
an `INSTCMD` or `SET VAR` requests; for details see docs/net-protocol.txt
and docs/sock-protocol.txt
- upsrw: display the variable type beside ENUM / RANGE
- Augeas: new `--with-augeas-lenses-dir` configure option.
Changes from 2.7.3 to 2.7.4
---------------------------
@ -171,7 +297,7 @@ Changes from 2.2.1 to 2.2.2
This enable the additional build and distribution of the static
version of libupsclient, along with the pkg-config helper and manual
pages. The default configure option is to distribute only the shared
version of libupsclient. This can be overriden by using the
version of libupsclient. This can be overridden by using the
"--disable-shared" configure option (distribute static only binaries).
- The UPS poweroff handling of the usbhid-ups driver has been reworked.
Though regression is not expected, users of this driver are
@ -182,7 +308,7 @@ Changes from 2.2.0 to 2.2.1
---------------------------
- nothing that affects upgraded systems.
(The below message is repetead due to previous omission)
(The below message is repeated due to previous omission)
- Developers of external client application using libupsclient are
encouraged to rename their "UPSCONN" client structure to "UPSCONN_t"
since the former will disappear by the release of NUT 2.4.

544
aclocal.m4 vendored
View file

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
# generated automatically by aclocal 1.16.3 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -20,146 +20,63 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# longlong.m4 serial 17
dnl Copyright (C) 1999-2007, 2009-2014 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Paul Eggert.
# Define HAVE_LONG_LONG_INT if 'long long int' works.
# This fixes a bug in Autoconf 2.61, and can be faster
# than what's in Autoconf 2.62 through 2.68.
# Note: If the type 'long long int' exists but is only 32 bits large
# (as on some very old compilers), HAVE_LONG_LONG_INT will not be
# defined. In this case you can treat 'long long int' like 'long int'.
AC_DEFUN([AC_TYPE_LONG_LONG_INT],
[
AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int],
[ac_cv_type_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
if test $ac_cv_type_long_long_int = yes; then
dnl Catch a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004.
dnl If cross compiling, assume the bug is not important, since
dnl nobody cross compiles for this platform as far as we know.
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[@%:@include <limits.h>
@%:@ifndef LLONG_MAX
@%:@ define HALF \
(1LL << (sizeof (long long int) * CHAR_BIT - 2))
@%:@ define LLONG_MAX (HALF - 1 + HALF)
@%:@endif]],
[[long long int n = 1;
int i;
for (i = 0; ; i++)
{
long long int m = n << i;
if (m >> i != n)
return 1;
if (LLONG_MAX / 2 < m)
break;
}
return 0;]])],
[],
[ac_cv_type_long_long_int=no],
[:])
fi
fi])
if test $ac_cv_type_long_long_int = yes; then
AC_DEFINE([HAVE_LONG_LONG_INT], [1],
[Define to 1 if the system has the type 'long long int'.])
fi
])
# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works.
# This fixes a bug in Autoconf 2.61, and can be faster
# than what's in Autoconf 2.62 through 2.68.
# Note: If the type 'unsigned long long int' exists but is only 32 bits
# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT
# will not be defined. In this case you can treat 'unsigned long long int'
# like 'unsigned long int'.
AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
[
AC_CACHE_CHECK([for unsigned long long int],
[ac_cv_type_unsigned_long_long_int],
[ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
AC_LINK_IFELSE(
[_AC_TYPE_LONG_LONG_SNIPPET],
[],
[ac_cv_type_unsigned_long_long_int=no])
fi])
if test $ac_cv_type_unsigned_long_long_int = yes; then
AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1],
[Define to 1 if the system has the type 'unsigned long long int'.])
fi
])
# Expands to a C program that can be used to test for simultaneous support
# of 'long long' and 'unsigned long long'. We don't want to say that
# 'long long' is available if 'unsigned long long' is not, or vice versa,
# because too many programs rely on the symmetry between signed and unsigned
# integer types (excluding 'bool').
AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
[
AC_LANG_PROGRAM(
[[/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;]],
[[/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));]])
])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
# 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.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# serial 12 (pkg-config-0.29.2)
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
# ----------------------------------
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
dnl 02111-1307, USA.
dnl
dnl As a special exception to the GNU General Public License, if you
dnl distribute this file as part of a program that contains a
dnl configuration script generated by Autoconf, you may include it under
dnl the same distribution terms that you use for the rest of that
dnl program.
dnl PKG_PREREQ(MIN-VERSION)
dnl -----------------------
dnl Since: 0.29
dnl
dnl Verify that the version of the pkg-config macros are at least
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
dnl installed version of pkg-config, this checks the developer's version
dnl of pkg.m4 when generating configure.
dnl
dnl To ensure that this macro is defined, also add:
dnl m4_ifndef([PKG_PREREQ],
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl ----------------------------------
dnl Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of
dnl pkg-config existed.
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@ -181,18 +98,19 @@ if test -n "$PKG_CONFIG"; then
PKG_CONFIG=""
fi
fi[]dnl
])# PKG_PROG_PKG_CONFIG
])dnl PKG_PROG_PKG_CONFIG
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# Check to see whether a particular set of modules exists. Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
# only at the first occurence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------------------------------
dnl Since: 0.18
dnl
dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
@ -202,8 +120,10 @@ m4_ifvaln([$3], [else
$3])dnl
fi])
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
dnl ---------------------------------------------
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
dnl pkg_failed based on the result.
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
@ -215,10 +135,11 @@ m4_define([_PKG_CONFIG],
else
pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
])dnl _PKG_CONFIG
# _PKG_SHORT_ERRORS_SUPPORTED
# -----------------------------
dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl ---------------------------
dnl Internal check to see if pkg-config supports short errors.
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@ -226,26 +147,24 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
else
_pkg_short_errors_supported=no
fi[]dnl
])# _PKG_SHORT_ERRORS_SUPPORTED
])dnl _PKG_SHORT_ERRORS_SUPPORTED
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
# [ACTION-IF-NOT-FOUND])
#
#
# Note that if there is a possibility the first call to
# PKG_CHECK_MODULES might not happen, you should be sure to include an
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
#
#
# --------------------------------------------------------------
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl --------------------------------------------------------------
dnl Since: 0.4.0
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $1])
AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
@ -292,16 +211,40 @@ else
AC_MSG_RESULT([yes])
$3
fi[]dnl
])# PKG_CHECK_MODULES
])dnl PKG_CHECK_MODULES
# PKG_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable pkgconfigdir as the location where a module
# should install pkg-config .pc files. By default the directory is
# $libdir/pkgconfig, but the default can be changed by passing
# DIRECTORY. The user can override through the --with-pkgconfigdir
# parameter.
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------------------
dnl Since: 0.29
dnl
dnl Checks for existence of MODULES and gathers its build flags with
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
dnl and VARIABLE-PREFIX_LIBS from --libs.
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
dnl configure.ac.
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
_save_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES($@)
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
])dnl PKG_CHECK_MODULES_STATIC
dnl PKG_INSTALLDIR([DIRECTORY])
dnl -------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable pkgconfigdir as the location where a module
dnl should install pkg-config .pc files. By default the directory is
dnl $libdir/pkgconfig, but the default can be changed by passing
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
dnl parameter.
AC_DEFUN([PKG_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
m4_pushdef([pkg_description],
@ -312,16 +255,18 @@ AC_ARG_WITH([pkgconfigdir],
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_INSTALLDIR
])dnl PKG_INSTALLDIR
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable noarch_pkgconfigdir as the location where a
# module should install arch-independent pkg-config .pc files. By
# default the directory is $datadir/pkgconfig, but the default can be
# changed by passing DIRECTORY. The user can override through the
# --with-noarch-pkgconfigdir parameter.
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
dnl --------------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
dnl module should install arch-independent pkg-config .pc files. By
dnl default the directory is $datadir/pkgconfig, but the default can be
dnl changed by passing DIRECTORY. The user can override through the
dnl --with-noarch-pkgconfigdir parameter.
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
m4_pushdef([pkg_description],
@ -332,13 +277,15 @@ AC_ARG_WITH([noarch-pkgconfigdir],
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_NOARCH_INSTALLDIR
])dnl PKG_NOARCH_INSTALLDIR
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
@ -347,9 +294,9 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])dnl PKG_CHECK_VAR
# Copyright (C) 2002-2013 Free Software Foundation, Inc.
# Copyright (C) 2002-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -361,10 +308,10 @@ AS_VAR_IF([$1], [""], [$5], [$4])dnl
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.14'
[am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.14.1], [],
m4_if([$1], [1.16.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@ -380,14 +327,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.14.1])dnl
[AM_AUTOMAKE_VERSION([1.16.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -439,7 +386,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2013 Free Software Foundation, Inc.
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -470,7 +417,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -661,13 +608,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
@ -675,49 +621,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
# TODO: see whether this extra hack can be removed once we start
# requiring Autoconf 2.70 or later.
AS_CASE([$CONFIG_FILES],
[*\'*], [eval set x "$CONFIG_FILES"],
[*], [set x $CONFIG_FILES])
shift
for mf
# Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named 'Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile which includes
# dependency-tracking related rules and includes.
# Grep'ing the whole file directly is not great: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|| continue
am_dirpart=`AS_DIRNAME(["$am_mf"])`
am_filepart=`AS_BASENAME(["$am_mf"])`
AM_RUN_LOG([cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles]) || am_rc=$?
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. If GNU make was not used, consider
re-running the configure script with MAKE="gmake" (or whatever is
necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running 'make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done
AS_UNSET([am_dirpart])
AS_UNSET([am_filepart])
AS_UNSET([am_mf])
AS_UNSET([am_rc])
rm -f conftest-deps.mk
}
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
@ -726,18 +666,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each '.P' file that we will
# need in order to bootstrap the dependency handling code.
# This code is only required when automatic dependency tracking is enabled.
# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
# order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
[AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -824,11 +763,11 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
@ -892,7 +831,7 @@ END
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>.
that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@ -902,6 +841,9 @@ END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
@ -931,7 +873,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -942,7 +884,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh}" != xset; then
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
@ -952,7 +894,7 @@ if test x"${install_sh}" != xset; then
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2013 Free Software Foundation, Inc.
# Copyright (C) 2003-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -974,7 +916,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1009,7 +951,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1017,49 +959,42 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
# Check whether make has an 'include' directive that can support all
# the idioms we need for our automatic dependency tracking code.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
cat > confinc.mk << 'END'
am__doit:
@echo this is the am__doit target
@echo this is the am__doit target >confinc.out
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# BSD make does it like this.
echo '.include "confinc.mk" # ignored' > confmf.BSD
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
echo 'include confinc.mk # ignored' > confmf.GNU
_am_result=no
for s in GNU BSD; do
AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
AS_CASE([$?:`cat confinc.out 2>/dev/null`],
['0:this is the am__doit target'],
[AS_CASE([$s],
[BSD], [am__include='.include' am__quote='"'],
[am__include='include' am__quote=''])])
if test "$am__include" != "#"; then
_am_result="yes ($s style)"
break
fi
done
rm -f confinc.* confmf.*
AC_MSG_RESULT([${_am_result}])
AC_SUBST([am__include])])
AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2013 Free Software Foundation, Inc.
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1080,12 +1015,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@ -1098,7 +1028,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1127,7 +1057,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1174,7 +1104,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1193,7 +1123,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1274,7 +1204,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
# Copyright (C) 2009-2013 Free Software Foundation, Inc.
# Copyright (C) 2009-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1334,7 +1264,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1362,7 +1292,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2013 Free Software Foundation, Inc.
# Copyright (C) 2006-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1381,7 +1311,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2013 Free Software Foundation, Inc.
# Copyright (C) 2004-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1512,7 +1442,11 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([m4/ax_c___attribute__.m4])
m4_include([m4/ax_c_pragmas.m4])
m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_compare_version.m4])
m4_include([m4/ax_run_or_link_ifelse.m4])
m4_include([m4/libtool.m4])
m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])
@ -1520,10 +1454,13 @@ m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
m4_include([m4/nut_arg_with.m4])
m4_include([m4/nut_check_asciidoc.m4])
m4_include([m4/nut_check_cppcheck.m4])
m4_include([m4/nut_check_headers_windows.m4])
m4_include([m4/nut_check_libavahi.m4])
m4_include([m4/nut_check_libfreeipmi.m4])
m4_include([m4/nut_check_libgd.m4])
m4_include([m4/nut_check_libltdl.m4])
m4_include([m4/nut_check_libmodbus.m4])
m4_include([m4/nut_check_libneon.m4])
m4_include([m4/nut_check_libnetsnmp.m4])
m4_include([m4/nut_check_libnss.m4])
@ -1532,5 +1469,10 @@ m4_include([m4/nut_check_libpowerman.m4])
m4_include([m4/nut_check_libusb.m4])
m4_include([m4/nut_check_libwrap.m4])
m4_include([m4/nut_check_os.m4])
m4_include([m4/nut_check_pkgconfig.m4])
m4_include([m4/nut_check_python.m4])
m4_include([m4/nut_compiler_family.m4])
m4_include([m4/nut_func_getnameinfo_argtypes.m4])
m4_include([m4/nut_report_feature.m4])
m4_include([m4/nut_stash_warnings.m4])
m4_include([m4/nut_type_socklen_t.m4])

View file

@ -1,7 +1,19 @@
# Network UPS Tools: clients
EXTRA_DIST =
# nutclient.cpp for some legacy reason (maybe initial detached development?)
# optionally includes "common.h" with the NUT build setup - and this option
# was never triggered in fact, not until pushed through command line like this:
AM_CXXFLAGS = -DHAVE_NUTCOMMON=1 -I$(top_srcdir)/include
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
$(top_builddir)/common/libcommon.la \
$(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 = ../common/libcommon.la libupsclient.la $(NETLIBS)
LDADD = $(top_builddir)/common/libcommon.la libupsclient.la $(NETLIBS)
if WITH_SSL
LDADD += $(LIBSSL_LIBS)
endif
@ -20,9 +32,13 @@ endif
bin_PROGRAMS = upsc upslog upsrw upscmd
dist_bin_SCRIPTS = upssched-cmd
sbin_PROGRAMS = upsmon upssched
lib_LTLIBRARIES = libupsclient.la libnutclient.la
lib_LTLIBRARIES = libupsclient.la
if HAVE_CXX11
lib_LTLIBRARIES += libnutclient.la
lib_LTLIBRARIES += libnutclientstub.la
endif
if WITH_DEV
include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h
include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h nutclientmem.h
endif
if WITH_CGI
cgiexec_PROGRAMS = upsstats.cgi upsimage.cgi upsset.cgi
@ -35,7 +51,7 @@ upslog_SOURCES = upslog.c upsclient.h upslog.h
upsmon_SOURCES = upsmon.c upsmon.h upsclient.h
upssched_SOURCES = upssched.c upssched.h
upssched_LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS)
upssched_LDADD = $(top_builddir)/common/libcommon.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)
@ -46,15 +62,44 @@ upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libcommonclient.la
libupsclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la
if WITH_SSL
libupsclient_la_LIBADD += $(LIBSSL_LIBS)
endif
# libupsclient version information
# Below we set API versions of public libraries
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
libupsclient_la_LDFLAGS = -version-info 4:0:0
# Note that changes here may have to be reflected in packaging (the shared
# object .so names would differ)
# libupsclient version information
libupsclient_la_LDFLAGS = -version-info 6:0:0 -export-symbols-regex ^upscli_
if HAVE_CXX11
# libnutclient version information and build
libnutclient_la_SOURCES = nutclient.h nutclient.cpp
libnutclient_la_LDFLAGS = -version-info 0:0:0
libnutclient_la_LDFLAGS = -version-info 2:0: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
else
EXTRA_DIST += nutclient.h nutclient.cpp
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_LIBADD = libnutclient.la
else
EXTRA_DIST += nutclientmem.h nutclientmem.cpp
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:
# rm -rf $(builddir)/.deps

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -14,13 +14,21 @@
@SET_MAKE@
# Network UPS Tools: clients
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -90,24 +98,31 @@ target_triplet = @target@
bin_PROGRAMS = upsc$(EXEEXT) upslog$(EXEEXT) upsrw$(EXEEXT) \
upscmd$(EXEEXT)
sbin_PROGRAMS = upsmon$(EXEEXT) upssched$(EXEEXT)
@HAVE_CXX11_TRUE@am__append_4 = libnutclient.la libnutclientstub.la
@WITH_CGI_TRUE@cgiexec_PROGRAMS = upsstats.cgi$(EXEEXT) \
@WITH_CGI_TRUE@ upsimage.cgi$(EXEEXT) upsset.cgi$(EXEEXT)
@WITH_SSL_TRUE@am__append_4 = $(LIBSSL_LIBS)
@WITH_SSL_TRUE@am__append_5 = $(LIBSSL_LIBS)
@HAVE_CXX11_FALSE@am__append_6 = nutclient.h nutclient.cpp \
@HAVE_CXX11_FALSE@ nutclientmem.h nutclientmem.cpp
subdir = clients
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(dist_bin_SCRIPTS) $(top_srcdir)/depcomp \
$(am__include_HEADERS_DIST)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -116,15 +131,26 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(dist_bin_SCRIPTS) \
$(am__include_HEADERS_DIST) $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cgiexecdir)" \
"$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"
PROGRAMS = $(bin_PROGRAMS) $(cgiexec_PROGRAMS) $(sbin_PROGRAMS)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@ -152,12 +178,11 @@ am__uninstall_files_from_dir = { \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libnutclient_la_LIBADD =
am_libnutclient_la_OBJECTS = nutclient.lo
@HAVE_CXX11_TRUE@libnutclient_la_DEPENDENCIES = \
@HAVE_CXX11_TRUE@ $(top_builddir)/common/libcommonclient.la
am__libnutclient_la_SOURCES_DIST = nutclient.h nutclient.cpp
@HAVE_CXX11_TRUE@am_libnutclient_la_OBJECTS = nutclient.lo
libnutclient_la_OBJECTS = $(am_libnutclient_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -167,9 +192,20 @@ libnutclient_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
$(AM_CXXFLAGS) $(CXXFLAGS) $(libnutclient_la_LDFLAGS) \
$(LDFLAGS) -o $@
@HAVE_CXX11_TRUE@am_libnutclient_la_rpath = -rpath $(libdir)
@HAVE_CXX11_TRUE@libnutclientstub_la_DEPENDENCIES = libnutclient.la
am__libnutclientstub_la_SOURCES_DIST = nutclientmem.h nutclientmem.cpp
@HAVE_CXX11_TRUE@am_libnutclientstub_la_OBJECTS = nutclientmem.lo
libnutclientstub_la_OBJECTS = $(am_libnutclientstub_la_OBJECTS)
libnutclientstub_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
$(AM_CXXFLAGS) $(CXXFLAGS) $(libnutclientstub_la_LDFLAGS) \
$(LDFLAGS) -o $@
@HAVE_CXX11_TRUE@am_libnutclientstub_la_rpath = -rpath $(libdir)
am__DEPENDENCIES_1 =
@WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libupsclient_la_DEPENDENCIES = ../common/libcommonclient.la \
libupsclient_la_DEPENDENCIES = \
$(top_builddir)/common/libcommonclient.la \
$(am__DEPENDENCIES_2)
am_libupsclient_la_OBJECTS = upsclient.lo
libupsclient_la_OBJECTS = $(am_libupsclient_la_OBJECTS)
@ -177,52 +213,51 @@ libupsclient_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libupsclient_la_LDFLAGS) $(LDFLAGS) \
-o $@
PROGRAMS = $(bin_PROGRAMS) $(cgiexec_PROGRAMS) $(sbin_PROGRAMS)
am_upsc_OBJECTS = upsc.$(OBJEXT)
upsc_OBJECTS = $(am_upsc_OBJECTS)
upsc_LDADD = $(LDADD)
upsc_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsc_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upscmd_OBJECTS = upscmd.$(OBJEXT)
upscmd_OBJECTS = $(am_upscmd_OBJECTS)
upscmd_LDADD = $(LDADD)
upscmd_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upscmd_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upsimage_cgi_OBJECTS = upsimage.$(OBJEXT) cgilib.$(OBJEXT)
upsimage_cgi_OBJECTS = $(am_upsimage_cgi_OBJECTS)
am__DEPENDENCIES_3 = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am__DEPENDENCIES_3 = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsimage_cgi_DEPENDENCIES = $(am__DEPENDENCIES_3) \
$(am__DEPENDENCIES_1)
am_upslog_OBJECTS = upslog.$(OBJEXT)
upslog_OBJECTS = $(am_upslog_OBJECTS)
upslog_LDADD = $(LDADD)
upslog_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upslog_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upsmon_OBJECTS = upsmon.$(OBJEXT)
upsmon_OBJECTS = $(am_upsmon_OBJECTS)
upsmon_LDADD = $(LDADD)
upsmon_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsmon_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upsrw_OBJECTS = upsrw.$(OBJEXT)
upsrw_OBJECTS = $(am_upsrw_OBJECTS)
upsrw_LDADD = $(LDADD)
upsrw_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsrw_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upssched_OBJECTS = upssched.$(OBJEXT)
upssched_OBJECTS = $(am_upssched_OBJECTS)
upssched_DEPENDENCIES = ../common/libcommon.la \
../common/libparseconf.la $(am__DEPENDENCIES_1)
upssched_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
$(top_builddir)/common/libparseconf.la $(am__DEPENDENCIES_1)
am_upsset_cgi_OBJECTS = upsset.$(OBJEXT) cgilib.$(OBJEXT)
upsset_cgi_OBJECTS = $(am_upsset_cgi_OBJECTS)
upsset_cgi_LDADD = $(LDADD)
upsset_cgi_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsset_cgi_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upsstats_cgi_OBJECTS = upsstats.$(OBJEXT) cgilib.$(OBJEXT)
upsstats_cgi_OBJECTS = $(am_upsstats_cgi_OBJECTS)
upsstats_cgi_LDADD = $(LDADD)
upsstats_cgi_DEPENDENCIES = ../common/libcommon.la libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
upsstats_cgi_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
libupsclient.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
SCRIPTS = $(dist_bin_SCRIPTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@ -238,7 +273,14 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/cgilib.Po ./$(DEPDIR)/nutclient.Plo \
./$(DEPDIR)/nutclientmem.Plo ./$(DEPDIR)/upsc.Po \
./$(DEPDIR)/upsclient.Plo ./$(DEPDIR)/upscmd.Po \
./$(DEPDIR)/upsimage.Po ./$(DEPDIR)/upslog.Po \
./$(DEPDIR)/upsmon.Po ./$(DEPDIR)/upsrw.Po \
./$(DEPDIR)/upssched.Po ./$(DEPDIR)/upsset.Po \
./$(DEPDIR)/upsstats.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -276,15 +318,16 @@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \
$(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \
$(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \
$(upssched_SOURCES) $(upsset_cgi_SOURCES) \
SOURCES = $(libnutclient_la_SOURCES) $(libnutclientstub_la_SOURCES) \
$(libupsclient_la_SOURCES) $(upsc_SOURCES) $(upscmd_SOURCES) \
$(upsimage_cgi_SOURCES) $(upslog_SOURCES) $(upsmon_SOURCES) \
$(upsrw_SOURCES) $(upssched_SOURCES) $(upsset_cgi_SOURCES) \
$(upsstats_cgi_SOURCES)
DIST_SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \
$(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \
$(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \
$(upssched_SOURCES) $(upsset_cgi_SOURCES) \
DIST_SOURCES = $(am__libnutclient_la_SOURCES_DIST) \
$(am__libnutclientstub_la_SOURCES_DIST) \
$(libupsclient_la_SOURCES) $(upsc_SOURCES) $(upscmd_SOURCES) \
$(upsimage_cgi_SOURCES) $(upslog_SOURCES) $(upsmon_SOURCES) \
$(upsrw_SOURCES) $(upssched_SOURCES) $(upsset_cgi_SOURCES) \
$(upsstats_cgi_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
@ -292,7 +335,7 @@ am__can_run_installinfo = \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__include_HEADERS_DIST = upsclient.h ../include/parseconf.h \
nutclient.h
nutclient.h nutclientmem.h
HEADERS = $(include_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
@ -313,6 +356,7 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A2X = @A2X@
ACLOCAL = @ACLOCAL@
@ -321,6 +365,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -331,6 +376,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -344,6 +390,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -356,6 +403,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -373,6 +421,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -383,21 +433,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -417,6 +475,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -430,6 +491,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -447,6 +509,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -460,6 +523,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -485,12 +551,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -501,8 +569,16 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
# Network UPS Tools: clients
EXTRA_DIST = $(am__append_6)
# nutclient.cpp for some legacy reason (maybe initial detached development?)
# optionally includes "common.h" with the NUT build setup - and this option
# was never triggered in fact, not until pushed through command line like this:
AM_CXXFLAGS = -DHAVE_NUTCOMMON=1 -I$(top_srcdir)/include
# by default, link programs in this directory with libcommon.a
LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) \
LDADD = $(top_builddir)/common/libcommon.la libupsclient.la $(NETLIBS) \
$(am__append_1)
# Avoid per-target CFLAGS, because this will prevent re-use of object
@ -510,15 +586,15 @@ LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) \
# but only add them if we really use the target.
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_2) $(am__append_3)
dist_bin_SCRIPTS = upssched-cmd
lib_LTLIBRARIES = libupsclient.la libnutclient.la
@WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h
lib_LTLIBRARIES = libupsclient.la $(am__append_4)
@WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h nutclientmem.h
upsc_SOURCES = upsc.c upsclient.h
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
upssched_SOURCES = upssched.c upssched.h
upssched_LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS)
upssched_LDADD = $(top_builddir)/common/libcommon.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)
upsset_cgi_SOURCES = upsset.c upsclient.h cgilib.c cgilib.h
@ -528,13 +604,29 @@ upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libcommonclient.la $(am__append_4)
libupsclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la \
$(am__append_5)
# Below we set API versions of public libraries
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
# Note that changes here may have to be reflected in packaging (the shared
# object .so names would differ)
# libupsclient version information
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
libupsclient_la_LDFLAGS = -version-info 4:0:0
libnutclient_la_SOURCES = nutclient.h nutclient.cpp
libnutclient_la_LDFLAGS = -version-info 0:0:0
libupsclient_la_LDFLAGS = -version-info 6:0:0 -export-symbols-regex ^upscli_
# libnutclient version information and build
@HAVE_CXX11_TRUE@libnutclient_la_SOURCES = nutclient.h nutclient.cpp
@HAVE_CXX11_TRUE@libnutclient_la_LDFLAGS = -version-info 2:0:0
# Needed in not-standalone builds with -DHAVE_NUTCOMMON=1
# which is defined for in-tree CXX builds above:
@HAVE_CXX11_TRUE@libnutclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la
# libnutclientstub version information and build
@HAVE_CXX11_TRUE@libnutclientstub_la_SOURCES = nutclientmem.h nutclientmem.cpp
@HAVE_CXX11_TRUE@libnutclientstub_la_LDFLAGS = -version-info 1:0:0
@HAVE_CXX11_TRUE@libnutclientstub_la_LIBADD = libnutclient.la
MAINTAINERCLEANFILES = Makefile.in .dirstamp
all: all-am
.SUFFIXES:
@ -551,14 +643,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu clients/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu clients/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -569,47 +660,6 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libnutclient.la: $(libnutclient_la_OBJECTS) $(libnutclient_la_DEPENDENCIES) $(EXTRA_libnutclient_la_DEPENDENCIES)
$(AM_V_CXXLD)$(libnutclient_la_LINK) -rpath $(libdir) $(libnutclient_la_OBJECTS) $(libnutclient_la_LIBADD) $(LIBS)
libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES) $(EXTRA_libupsclient_la_DEPENDENCIES)
$(AM_V_CCLD)$(libupsclient_la_LINK) -rpath $(libdir) $(libupsclient_la_OBJECTS) $(libupsclient_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
@ -758,6 +808,50 @@ clean-sbinPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libnutclient.la: $(libnutclient_la_OBJECTS) $(libnutclient_la_DEPENDENCIES) $(EXTRA_libnutclient_la_DEPENDENCIES)
$(AM_V_CXXLD)$(libnutclient_la_LINK) $(am_libnutclient_la_rpath) $(libnutclient_la_OBJECTS) $(libnutclient_la_LIBADD) $(LIBS)
libnutclientstub.la: $(libnutclientstub_la_OBJECTS) $(libnutclientstub_la_DEPENDENCIES) $(EXTRA_libnutclientstub_la_DEPENDENCIES)
$(AM_V_CXXLD)$(libnutclientstub_la_LINK) $(am_libnutclientstub_la_rpath) $(libnutclientstub_la_OBJECTS) $(libnutclientstub_la_LIBADD) $(LIBS)
libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES) $(EXTRA_libupsclient_la_DEPENDENCIES)
$(AM_V_CCLD)$(libupsclient_la_LINK) -rpath $(libdir) $(libupsclient_la_OBJECTS) $(libupsclient_la_LIBADD) $(LIBS)
upsc$(EXEEXT): $(upsc_OBJECTS) $(upsc_DEPENDENCIES) $(EXTRA_upsc_DEPENDENCIES)
@rm -f upsc$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(upsc_OBJECTS) $(upsc_LDADD) $(LIBS)
@ -835,18 +929,25 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgilib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nutclient.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsclient.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upscmd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsimage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upslog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsmon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsrw.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upssched.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsstats.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgilib.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nutclient.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nutclientmem.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsclient.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upscmd.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsimage.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upslog.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsmon.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsrw.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upssched.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsset.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsstats.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@ -975,7 +1076,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -1007,11 +1111,11 @@ distdir: $(DISTFILES)
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(HEADERS)
all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(HEADERS)
install-binPROGRAMS: install-libLTLIBRARIES
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@ -1044,6 +1148,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-binPROGRAMS clean-cgiexecPROGRAMS clean-generic \
@ -1051,7 +1156,19 @@ clean-am: clean-binPROGRAMS clean-cgiexecPROGRAMS clean-generic \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f ./$(DEPDIR)/cgilib.Po
-rm -f ./$(DEPDIR)/nutclient.Plo
-rm -f ./$(DEPDIR)/nutclientmem.Plo
-rm -f ./$(DEPDIR)/upsc.Po
-rm -f ./$(DEPDIR)/upsclient.Plo
-rm -f ./$(DEPDIR)/upscmd.Po
-rm -f ./$(DEPDIR)/upsimage.Po
-rm -f ./$(DEPDIR)/upslog.Po
-rm -f ./$(DEPDIR)/upsmon.Po
-rm -f ./$(DEPDIR)/upsrw.Po
-rm -f ./$(DEPDIR)/upssched.Po
-rm -f ./$(DEPDIR)/upsset.Po
-rm -f ./$(DEPDIR)/upsstats.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -1099,7 +1216,19 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f ./$(DEPDIR)/cgilib.Po
-rm -f ./$(DEPDIR)/nutclient.Plo
-rm -f ./$(DEPDIR)/nutclientmem.Plo
-rm -f ./$(DEPDIR)/upsc.Po
-rm -f ./$(DEPDIR)/upsclient.Plo
-rm -f ./$(DEPDIR)/upscmd.Po
-rm -f ./$(DEPDIR)/upsimage.Po
-rm -f ./$(DEPDIR)/upslog.Po
-rm -f ./$(DEPDIR)/upsmon.Po
-rm -f ./$(DEPDIR)/upsrw.Po
-rm -f ./$(DEPDIR)/upssched.Po
-rm -f ./$(DEPDIR)/upsset.Po
-rm -f ./$(DEPDIR)/upsstats.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@ -1122,7 +1251,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-cgiexecPROGRAMS \
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-binPROGRAMS clean-cgiexecPROGRAMS clean-generic \
clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS \
cscopelist-am ctags ctags-am distclean distclean-compile \
@ -1142,6 +1271,21 @@ uninstall-am: uninstall-binPROGRAMS uninstall-cgiexecPROGRAMS \
uninstall-dist_binSCRIPTS uninstall-includeHEADERS \
uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS
.PRECIOUS: Makefile
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
$(top_builddir)/common/libcommon.la \
$(top_builddir)/common/libcommonclient.la \
$(top_builddir)/common/libparseconf.la: dummy
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
dummy:
# 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
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View file

@ -46,9 +46,12 @@ static char *unescape(char *buf)
hex[1] = buf[++i];
hex[2] = '\0';
if (!isxdigit((unsigned char) hex[0])
|| !isxdigit((unsigned char) hex[0]))
|| !isxdigit((unsigned char) hex[1]))
fatalx(EXIT_FAILURE, "bad escape char");
ch = strtol(hex, NULL, 16);
long 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... */
if ((ch == 10) || (ch == 13))
ch = ' ';

View file

@ -17,6 +17,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_CGILIB_H_SEEN
#define NUT_CGILIB_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
@ -41,3 +44,4 @@ int checkhost(const char *host, char **desc);
/* *INDENT-ON* */
#endif
#endif /* NUT_CGILIB_H_SEEN */

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,13 @@
#include <map>
#include <set>
#include <exception>
#include <cstdint>
#include <ctime>
/* See include/common.h for details behind this */
#ifndef NUT_UNUSED_VARIABLE
#define NUT_UNUSED_VARIABLE(x) (void)(x)
#endif
namespace nut
{
@ -51,9 +58,11 @@ class NutException : public std::exception
{
public:
NutException(const std::string& msg):_msg(msg){}
virtual ~NutException() throw() {}
virtual const char * what() const throw() {return this->_msg.c_str();}
virtual std::string str() const throw() {return this->_msg;}
NutException(const NutException&) = default;
NutException& operator=(NutException& rhs) = default;
virtual ~NutException() override;
virtual const char * what() const noexcept override {return this->_msg.c_str();}
virtual std::string str() const noexcept {return this->_msg;}
private:
std::string _msg;
};
@ -65,7 +74,9 @@ class SystemException : public NutException
{
public:
SystemException();
virtual ~SystemException() throw() {}
SystemException(const SystemException&) = default;
SystemException& operator=(SystemException& rhs) = default;
virtual ~SystemException() override;
private:
static std::string err();
};
@ -78,7 +89,9 @@ class IOException : public NutException
{
public:
IOException(const std::string& msg):NutException(msg){}
virtual ~IOException() throw() {}
IOException(const IOException&) = default;
IOException& operator=(IOException& rhs) = default;
virtual ~IOException() override;
};
/**
@ -88,7 +101,9 @@ class UnknownHostException : public IOException
{
public:
UnknownHostException():IOException("Unknown host"){}
virtual ~UnknownHostException() throw() {}
UnknownHostException(const UnknownHostException&) = default;
UnknownHostException& operator=(UnknownHostException& rhs) = default;
virtual ~UnknownHostException() override;
};
/**
@ -98,7 +113,9 @@ class NotConnectedException : public IOException
{
public:
NotConnectedException():IOException("Not connected"){}
virtual ~NotConnectedException() throw() {}
NotConnectedException(const NotConnectedException&) = default;
NotConnectedException& operator=(NotConnectedException& rhs) = default;
virtual ~NotConnectedException() override;
};
/**
@ -108,9 +125,30 @@ class TimeoutException : public IOException
{
public:
TimeoutException():IOException("Timeout"){}
virtual ~TimeoutException() throw() {}
TimeoutException(const TimeoutException&) = default;
TimeoutException& operator=(TimeoutException& rhs) = default;
virtual ~TimeoutException() override;
};
/**
* Cookie given when performing async action, used to redeem result at a later date.
*/
typedef std::string TrackingID;
/**
* Result of an async action.
*/
typedef enum
{
UNKNOWN,
PENDING,
SUCCESS,
INVALID_ARGUMENT,
FAILURE,
} TrackingResult;
typedef std::string Feature;
/**
* A nut client is the starting point to dialog to NUTD.
* It can connect to an NUTD then retrieve its device list.
@ -122,7 +160,7 @@ class Client
friend class Variable;
friend class Command;
public:
~Client();
virtual ~Client();
/**
* Intend to authenticate to a NUTD server.
@ -132,13 +170,13 @@ public:
* \todo Is his method is global to all connection protocol or is it specific to TCP ?
* \note Actually, authentication fails only if already set, not if bad values are sent.
*/
virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException)=0;
virtual void authenticate(const std::string& user, const std::string& passwd) = 0;
/**
* Disconnect from the NUTD server.
* \todo Is his method is global to all connection protocol or is it specific to TCP ?
*/
virtual void logout()throw(NutException)=0;
virtual void logout() = 0;
/**
* Device manipulations.
@ -151,29 +189,29 @@ public:
* \param name Name of the device.
* \return The device.
*/
virtual Device getDevice(const std::string& name)throw(NutException);
virtual Device getDevice(const std::string& name);
/**
* Retrieve the list of all devices supported by UPSD server.
* \return The set of supported devices.
*/
virtual std::set<Device> getDevices()throw(NutException);
virtual std::set<Device> getDevices();
/**
* Test if a device is supported by the NUTD server.
* \param dev Device name.
* \return true if supported, false otherwise.
*/
virtual bool hasDevice(const std::string& dev)throw(NutException);
virtual bool hasDevice(const std::string& dev);
/**
* Retrieve names of devices supported by NUTD server.
* \return The set of names of supported devices.
*/
virtual std::set<std::string> getDeviceNames()throw(NutException)=0;
virtual std::set<std::string> getDeviceNames() = 0;
/**
* Retrieve the description of a device.
* \param name Device name.
* \return Device description.
*/
virtual std::string getDeviceDescription(const std::string& name)throw(NutException)=0;
virtual std::string getDeviceDescription(const std::string& name) = 0;
/** \} */
/**
@ -186,54 +224,60 @@ public:
* \param dev Device name
* \return Variable names
*/
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev)throw(NutException)=0;
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev) = 0;
/**
* Retrieve names of read/write variables supported by a device.
* \param dev Device name
* \return RW variable names
*/
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev)throw(NutException)=0;
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev) = 0;
/**
* Test if a variable is supported by a device.
* \param dev Device name
* \param name Variable name
* \return true if the variable is supported.
*/
virtual bool hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException);
virtual bool hasDeviceVariable(const std::string& dev, const std::string& name);
/**
* Retrieve the description of a variable.
* \param dev Device name
* \param name Variable name
* \return Variable description if provided.
*/
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)=0;
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name) = 0;
/**
* Retrieve values of a variable.
* \param dev Device name
* \param name Variable name
* \return Variable values (usually one) if available.
*/
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)=0;
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name) = 0;
/**
* Retrieve values of all variables of a device.
* \param dev Device name
* \return Variable values indexed by variable names.
*/
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev)throw(NutException);
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev);
/**
* Retrieve values of all variables of a set of devices.
* \param devs Device names
* \return Variable values indexed by variable names, indexed by device names.
*/
virtual std::map<std::string,std::map<std::string,std::vector<std::string> > > getDevicesVariableValues(const std::set<std::string>& devs);
/**
* Intend to set the value of a variable.
* \param dev Device name
* \param name Variable name
* \param value Variable value
*/
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)=0;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value) = 0;
/**
* Intend to set the value of a variable.
* \param dev Device name
* \param name Variable name
* \param value Variable value
* \param values Vector of variable values
*/
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values)throw(NutException)=0;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values) = 0;
/** \} */
/**
@ -246,27 +290,28 @@ public:
* \param dev Device name
* \return Command names
*/
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev)throw(NutException)=0;
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev) = 0;
/**
* Test if a command is supported by a device.
* \param dev Device name
* \param name Command name
* \return true if the command is supported.
*/
virtual bool hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException);
virtual bool hasDeviceCommand(const std::string& dev, const std::string& name);
/**
* Retrieve the description of a command.
* \param dev Device name
* \param name Command name
* \return Command description if provided.
*/
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)=0;
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name) = 0;
/**
* Intend to execute a command.
* \param dev Device name
* \param name Command name
* \param param Additional command parameter
*/
virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)=0;
virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param="") = 0;
/** \} */
/**
@ -277,15 +322,33 @@ public:
* Log the current user (if authenticated) for a device.
* \param dev Device name.
*/
virtual void deviceLogin(const std::string& dev)throw(NutException)=0;
virtual void deviceLogin(const std::string& dev) = 0;
/**
* Retrieve the number of user longged in the specified device.
* Retrieve the number of user logged-in for the specified device.
* \param dev Device name.
* \return Number of logged-in users.
*/
virtual int deviceGetNumLogins(const std::string& dev)throw(NutException)=0;
virtual void deviceMaster(const std::string& dev)throw(NutException)=0;
virtual void deviceForcedShutdown(const std::string& dev)throw(NutException)=0;
virtual int deviceGetNumLogins(const std::string& dev) = 0;
/* NOTE: "master" is deprecated since NUT v2.8.0 in favor of "primary".
* For the sake of old/new server/client interoperability,
* practical implementations should try to use one and fall
* back to the other, and only fail if both return "ERR".
*/
virtual void deviceMaster(const std::string& dev) = 0;
virtual void devicePrimary(const std::string& dev) = 0;
virtual void deviceForcedShutdown(const std::string& dev) = 0;
/**
* Retrieve the result of a tracking ID.
* \param id Tracking ID.
*/
virtual TrackingResult getTrackingResult(const TrackingID& id) = 0;
virtual bool hasFeature(const Feature& feature);
virtual bool isFeatureEnabled(const Feature& feature) = 0;
virtual void setFeature(const Feature& feature, bool status) = 0;
static const Feature TRACKING;
protected:
Client();
@ -297,6 +360,11 @@ protected:
*/
class TcpClient : public Client
{
/* We have a number of direct-call methods we do not expose
* generally, but still want covered with integration tests
*/
friend class NutActiveClientTest;
public:
/**
* Construct a nut TcpClient object.
@ -309,21 +377,21 @@ public:
* \param host Server host name.
* \param port Server port.
*/
TcpClient(const std::string& host, int port = 3493)throw(nut::IOException);
~TcpClient();
TcpClient(const std::string& host, uint16_t port = 3493);
~TcpClient() override;
/**
* Connect it to the specified server.
* \param host Server host name.
* \param port Server port.
*/
void connect(const std::string& host, int port = 3493)throw(nut::IOException);
void connect(const std::string& host, uint16_t port = 3493);
/**
* Connect to the server.
* Host name and ports must have already set (usefull for reconnection).
*/
void connect()throw(nut::IOException);
void connect();
/**
* Test if the connection is active.
@ -339,13 +407,13 @@ public:
* Set the timeout in seconds.
* \param timeout Timeout n seconds, negative to block operations.
*/
void setTimeout(long timeout);
void setTimeout(time_t timeout);
/**
* Retrieve the timeout.
* \returns Current timeout in seconds.
*/
long getTimeout()const;
time_t getTimeout()const;
/**
* Retriueve the host name of the server the client is connected to.
@ -356,53 +424,64 @@ public:
* Retriueve the port of host of the server the client is connected to.
* \return Server port
*/
int getPort()const;
uint16_t getPort()const;
virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException);
virtual void logout()throw(NutException);
virtual void authenticate(const std::string& user, const std::string& passwd) override;
virtual void logout() override;
virtual Device getDevice(const std::string& name)throw(NutException);
virtual std::set<std::string> getDeviceNames()throw(NutException);
virtual std::string getDeviceDescription(const std::string& name)throw(NutException);
virtual Device getDevice(const std::string& name) override;
virtual std::set<std::string> getDeviceNames() override;
virtual std::string getDeviceDescription(const std::string& name) override;
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev)throw(NutException);
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev)throw(NutException);
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException);
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException);
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev)throw(NutException);
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException);
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values)throw(NutException);
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev) override;
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev) override;
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name) override;
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name) override;
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev) override;
virtual std::map<std::string,std::map<std::string,std::vector<std::string> > > getDevicesVariableValues(const std::set<std::string>& devs) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values) override;
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev)throw(NutException);
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException);
virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException);
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev) override;
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name) override;
virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param="") override;
virtual void deviceLogin(const std::string& dev)throw(NutException);
virtual void deviceMaster(const std::string& dev)throw(NutException);
virtual void deviceForcedShutdown(const std::string& dev)throw(NutException);
virtual int deviceGetNumLogins(const std::string& dev)throw(NutException);
virtual void deviceLogin(const std::string& dev) override;
/* FIXME: Protocol update needed to handle master/primary alias
* and probably an API bump also, to rename/alias the routine.
*/
virtual void deviceMaster(const std::string& dev) override;
virtual void devicePrimary(const std::string& dev) override;
virtual void deviceForcedShutdown(const std::string& dev) override;
virtual int deviceGetNumLogins(const std::string& dev) override;
virtual TrackingResult getTrackingResult(const TrackingID& id) override;
virtual bool isFeatureEnabled(const Feature& feature) override;
virtual void setFeature(const Feature& feature, bool status) override;
protected:
std::string sendQuery(const std::string& req)throw(nut::IOException);
static void detectError(const std::string& req)throw(nut::NutException);
std::string sendQuery(const std::string& req);
void sendAsyncQueries(const std::vector<std::string>& req);
static void detectError(const std::string& req);
TrackingID sendTrackingQuery(const std::string& req);
std::vector<std::string> get(const std::string& subcmd, const std::string& params = "")
throw(nut::NutException);
std::vector<std::string> get(const std::string& subcmd, const std::string& params = "");
std::vector<std::vector<std::string> > list(const std::string& subcmd, const std::string& params = "")
throw(nut::NutException);
std::vector<std::vector<std::string> > list(const std::string& subcmd, const std::string& params = "");
std::vector<std::vector<std::string> > parseList(const std::string& req);
static std::vector<std::string> explode(const std::string& str, size_t begin=0);
static std::string escape(const std::string& str);
private:
std::string _host;
int _port;
long _timeout;
uint16_t _port;
time_t _timeout;
internal::Socket* _socket;
};
/**
* Device attached to a client.
* Device is a lightweight class which can be copied easily.
@ -411,9 +490,14 @@ class Device
{
friend class Client;
friend class TcpClient;
friend class TcpClientMock;
#ifdef _NUTCLIENTTEST_BUILD
friend class NutClientTest;
#endif
public:
~Device();
Device(const Device& dev);
Device& operator=(const Device& dev);
/**
* Retrieve the name of the device.
@ -455,92 +539,97 @@ public:
/**
* Retrieve the description of the devce if specified.
*/
std::string getDescription()throw(NutException);
std::string getDescription();
/**
* Intend to retrieve the value of a variable of the device.
* \param name Name of the variable to get.
* \return Value of the variable, if available.
*/
std::vector<std::string> getVariableValue(const std::string& name)throw(NutException);
std::vector<std::string> getVariableValue(const std::string& name);
/**
* Intend to retrieve values of all variables of the devices.
* \return Map of all variables values indexed by their names.
*/
std::map<std::string,std::vector<std::string> > getVariableValues()throw(NutException);
std::map<std::string,std::vector<std::string> > getVariableValues();
/**
* Retrieve all variables names supported by the device.
* \return Set of available variable names.
*/
std::set<std::string> getVariableNames()throw(NutException);
std::set<std::string> getVariableNames();
/**
* Retrieve all Read/Write variables names supported by the device.
* \return Set of available Read/Write variable names.
*/
std::set<std::string> getRWVariableNames()throw(NutException);
std::set<std::string> getRWVariableNames();
/**
* Intend to set the value of a variable of the device.
* \param name Variable name.
* \param value New variable value.
*/
void setVariable(const std::string& name, const std::string& value)throw(NutException);
void setVariable(const std::string& name, const std::string& value);
/**
* Intend to set values of a variable of the device.
* \param name Variable name.
* \param value New variable values.
* \param values Vector of new variable values.
*/
void setVariable(const std::string& name, const std::vector<std::string>& values)throw(NutException);
void setVariable(const std::string& name, const std::vector<std::string>& values);
/**
* Retrieve a Variable object representing the specified variable.
* \param name Variable name.
* \return Variable object.
*/
Variable getVariable(const std::string& name)throw(NutException);
Variable getVariable(const std::string& name);
/**
* Retrieve Variable objects representing all variables available for the device.
* \return Set of Variable objects.
*/
std::set<Variable> getVariables()throw(NutException);
std::set<Variable> getVariables();
/**
* Retrieve Variable objects representing all Read/Write variables available for the device.
* \return Set of Variable objects.
*/
std::set<Variable> getRWVariables()throw(NutException);
std::set<Variable> getRWVariables();
/**
* Retrieve names of all commands supported by the device.
* \return Set of available command names.
*/
std::set<std::string> getCommandNames()throw(NutException);
std::set<std::string> getCommandNames();
/**
* Retrieve objects for all commands supported by the device.
* \return Set of available Command objects.
*/
std::set<Command> getCommands()throw(NutException);
std::set<Command> getCommands();
/**
* Retrieve an object representing a command of the device.
* \param name Command name.
* \return Command object.
*/
Command getCommand(const std::string& name)throw(NutException);
Command getCommand(const std::string& name);
/**
* Intend to execute a command on the device.
* \param name Command name.
* \param param Additional command parameter
*/
void executeCommand(const std::string& name)throw(NutException);
TrackingID executeCommand(const std::string& name, const std::string& param="");
/**
* Login current client's user for the device.
*/
void login()throw(NutException);
void master()throw(NutException);
void forcedShutdown()throw(NutException);
void login();
/* FIXME: Protocol update needed to handle master/primary alias
* and probably an API bump also, to rename/alias the routine.
*/
void master();
void primary();
void forcedShutdown();
/**
* Retrieve the number of logged user for the device.
* \return Number of users.
*/
int getNumLogins()throw(NutException);
int getNumLogins();
protected:
Device(Client* client, const std::string& name);
@ -558,10 +647,15 @@ class Variable
{
friend class Device;
friend class TcpClient;
friend class TcpClientMock;
#ifdef _NUTCLIENTTEST_BUILD
friend class NutClientTest;
#endif
public:
~Variable();
Variable(const Variable& var);
Variable& operator=(const Variable& var);
/**
* Retrieve variable name.
@ -603,23 +697,23 @@ public:
* Intend to retrieve variable value.
* \return Value of the variable.
*/
std::vector<std::string> getValue()throw(NutException);
std::vector<std::string> getValue();
/**
* Intend to retireve variable description.
* \return Variable description if provided.
*/
std::string getDescription()throw(NutException);
std::string getDescription();
/**
* Intend to set a value to the variable.
* \param value New variable value.
*/
void setValue(const std::string& value)throw(NutException);
void setValue(const std::string& value);
/**
* Intend to set (multiple) values to the variable.
* \param value New variable values.
* \param values Vector of new variable values.
*/
void setValues(const std::vector<std::string>& values)throw(NutException);
void setValues(const std::vector<std::string>& values);
protected:
Variable(Device* dev, const std::string& name);
@ -637,10 +731,15 @@ class Command
{
friend class Device;
friend class TcpClient;
friend class TcpClientMock;
#ifdef _NUTCLIENTTEST_BUILD
friend class NutClientTest;
#endif
public:
~Command();
Command(const Command& cmd);
Command& operator=(const Command& cmd);
/**
* Retrieve command name.
@ -683,13 +782,13 @@ public:
* Intend to retireve command description.
* \return Command description if provided.
*/
std::string getDescription()throw(NutException);
std::string getDescription();
/**
* Intend to retrieve command description.
* \return Command description if provided.
* Intend to execute the instant command on device.
* \param param Optional additional command parameter
*/
void execute()throw(NutException);
void execute(const std::string& param="");
protected:
Command(Device* dev, const std::string& name);
@ -722,13 +821,19 @@ typedef char** strarr;
/**
* Alloc an array of string.
*/
strarr strarr_alloc(unsigned short count);
strarr strarr_alloc(size_t count);
/**
* Free an array of string.
*/
void strarr_free(strarr arr);
/**
* Convert C++ types into an array of string.
*/
strarr stringvector_to_strarr(const std::vector<std::string>& strset);
strarr stringset_to_strarr(const std::set<std::string>& strset);
/**
* Nut general client types and functions.
@ -776,7 +881,11 @@ int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev);
* \param client Nut client handle.
* \param dev Device name to test.
*/
/* FIXME: Protocol update needed to handle master/primary alias
* and probably an API bump also, to rename/alias the routine.
*/
void nutclient_device_master(NUTCLIENT_t client, const char* dev);
void nutclient_device_primary(NUTCLIENT_t client, const char* dev);
/**
* Set the FSD flag for the device.
@ -901,7 +1010,7 @@ char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* d
* \param dev Device name.
* \param cmd Command name.
*/
void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd);
void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd, const char* param="");
/** \} */
@ -920,9 +1029,9 @@ typedef NUTCLIENT_t NUTCLIENT_TCP_t;
* Create a client to NUTD using a TCP connection.
* \param host Host name to connect to.
* \param port Host port.
* \return New client or NULL if failed.
* \return New client or nullptr if failed.
*/
NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port);
NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, uint16_t port);
/**
* Test if a nut TCP client is connected.
* \param client Nut TCP client handle.
@ -945,12 +1054,12 @@ int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client);
* Set the timeout value for the TCP connection.
* \param timeout Timeout in seconds, negative for blocking.
*/
void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout);
void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, time_t timeout);
/**
* Retrieve the timeout value for the TCP connection.
* \return Timeout value in seconds.
*/
long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client);
time_t nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client);
/** \} */

252
clients/nutclientmem.cpp Normal file
View file

@ -0,0 +1,252 @@
/* nutclientmem.cpp - nutclientmem C++ library implementation
Copyright (C) 2021 Eric Clappier <ericclappier@eaton.com>
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 "nutclientmem.h"
#include <common.h>
namespace nut
{
/*
*
* Memory Client stub implementation
*
*/
Device MemClientStub::getDevice(const std::string& name)
{
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceNames()
{
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceDescription(const std::string& name)
{
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceVariableNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceRWVariableNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceVariableDescription(const std::string& dev, const std::string& name)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
ListValue MemClientStub::getDeviceVariableValue(const std::string& dev, const std::string& name)
{
ListValue res;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
auto map = it_dev->second;
auto it_map = map.find(name);
if (it_map != map.end())
{
res = it_map->second;
}
}
return res;
}
ListObject MemClientStub::getDeviceVariableValues(const std::string& dev)
{
ListObject res;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
res = it_dev->second;
}
return res;
}
ListDevice MemClientStub::getDevicesVariableValues(const std::set<std::string>& devs)
{
ListDevice res;
for (auto itr = devs.begin(); itr != devs.end(); itr++)
{
std::string dev = *itr;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
res.insert(std::pair<std::string, ListObject>(dev, it_dev->second));
}
}
return res;
}
TrackingID MemClientStub::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)
{
auto it_dev = _values.find(dev);
if (it_dev == _values.end())
{
ListObject list;
_values.emplace(dev, list);
it_dev = _values.find(dev);
}
if (it_dev != _values.end())
{
auto map = &(it_dev->second);
auto it_map = map->find(name);
if (it_map != map->end())
{
it_map->second[0] = value;
}
else
{
ListValue list_value;
list_value.push_back(value);
map->emplace(name, list_value);
}
}
return "";
}
TrackingID MemClientStub::setDeviceVariable(const std::string& dev, const std::string& name, const ListValue& values)
{
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
auto map = &(it_dev->second);
auto it_map = map->find(name);
if (it_map != map->end())
{
it_map->second = values;
}
else
{
map->emplace(name, values);
}
}
return "";
}
std::set<std::string> MemClientStub::getDeviceCommandNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceCommandDescription(const std::string& dev, const std::string& name)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
TrackingID MemClientStub::executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
NUT_UNUSED_VARIABLE(param);
throw NutException("Not implemented");
}
void MemClientStub::deviceLogin(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
/* Note: "master" is deprecated, but supported
* for mixing old/new client/server combos: */
void MemClientStub::deviceMaster(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
void MemClientStub::devicePrimary(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
void MemClientStub::deviceForcedShutdown(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
int MemClientStub::deviceGetNumLogins(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
TrackingResult MemClientStub::getTrackingResult(const TrackingID& id)
{
NUT_UNUSED_VARIABLE(id);
throw NutException("Not implemented");
//return TrackingResult::SUCCESS;
}
bool MemClientStub::isFeatureEnabled(const Feature& feature)
{
NUT_UNUSED_VARIABLE(feature);
throw NutException("Not implemented");
}
void MemClientStub::setFeature(const Feature& feature, bool status)
{
NUT_UNUSED_VARIABLE(feature);
NUT_UNUSED_VARIABLE(status);
throw NutException("Not implemented");
}
} /* namespace nut */
/**
* C nutclient API.
*/
extern "C" {
NUTCLIENT_MEM_t nutclient_mem_create_client()
{
nut::MemClientStub* client = new nut::MemClientStub;
try
{
return static_cast<NUTCLIENT_MEM_t>(client);
}
catch(nut::NutException& ex)
{
// TODO really catch it
NUT_UNUSED_VARIABLE(ex);
delete client;
return nullptr;
}
}
} /* extern "C" */

118
clients/nutclientmem.h Normal file
View file

@ -0,0 +1,118 @@
/* nutclientmem.h - definitions for nutclientmem C/C++ library
Copyright (C) 2021 Eric Clappier <ericclappier@eaton.com>
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 NUTCLIENTMEM_HPP_SEEN
#define NUTCLIENTMEM_HPP_SEEN
/* Begin of C++ nutclient library declaration */
#ifdef __cplusplus
#include "nutclient.h"
namespace nut
{
typedef std::vector<std::string> ListValue;
typedef std::map<std::string, ListValue> ListObject;
typedef std::map<std::string, ListObject> ListDevice;
/**
* Memory client stub.
* Class to stub TCPClient for test (data store in local memory).
*/
class MemClientStub : public Client
{
public:
/**
* Construct a nut MemClientStub object.
*/
MemClientStub() {}
~MemClientStub() override {}
virtual void authenticate(const std::string& user, const std::string& passwd) override {
NUT_UNUSED_VARIABLE(user);
NUT_UNUSED_VARIABLE(passwd);
}
virtual void logout() override {}
virtual Device getDevice(const std::string& name) override;
virtual std::set<std::string> getDeviceNames() override;
virtual std::string getDeviceDescription(const std::string& name) override;
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev) override;
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev) override;
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name) override;
virtual ListValue getDeviceVariableValue(const std::string& dev, const std::string& name) override;
virtual ListObject getDeviceVariableValues(const std::string& dev) override;
virtual ListDevice getDevicesVariableValues(const std::set<std::string>& devs) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const ListValue& values) override;
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev) override;
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name) override;
virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param="") override;
virtual void deviceLogin(const std::string& dev) override;
/* Note: "master" is deprecated, but supported
* for mixing old/new client/server combos: */
virtual void deviceMaster(const std::string& dev) override;
virtual void devicePrimary(const std::string& dev) override;
virtual void deviceForcedShutdown(const std::string& dev) override;
virtual int deviceGetNumLogins(const std::string& dev) override;
virtual TrackingResult getTrackingResult(const TrackingID& id) override;
virtual bool isFeatureEnabled(const Feature& feature) override;
virtual void setFeature(const Feature& feature, bool status) override;
private:
ListDevice _values;
};
} /* namespace nut */
#endif /* __cplusplus */
/* End of C++ nutclient library declaration */
/* Begin of C nutclient library declaration */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Nut MEM client dedicated types and functions
*/
/**
* Hidden structure representing a MEM connection.
* NUTCLIENT_MEM_t is back compatible to NUTCLIENT_t.
*/
typedef NUTCLIENT_t NUTCLIENT_MEM_t;
/**
* Create a client to NUTD using memory.
* \return New client or nullptr if failed.
*/
NUTCLIENT_MEM_t nutclient_mem_create_client();
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* End of C nutclient library declaration */
#endif /* NUTCLIENTMOCK_HPP_SEEN */

View file

@ -17,13 +17,19 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_STATUS_H_SEEN
#define NUT_STATUS_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
struct {
/* This is only used in upsstats.c, but might it also have external consumers?..
* To move or not to move?..
*/
static struct {
char *name;
char *desc;
int severity;
@ -48,3 +54,4 @@ struct {
/* *INDENT-ON* */
#endif
#endif /* NUT_STATUS_H_SEEN */

View file

@ -25,6 +25,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
static char *upsname = NULL, *hostname = NULL;
@ -58,7 +59,7 @@ static void usage(const char *prog)
static void printvar(const char *var)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -86,7 +87,7 @@ static void printvar(const char *var)
}
if (numa < numq) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least %d)", numa, numq);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least %zu)", numa, numq);
}
printf("%s\n", answer[3]);
@ -95,7 +96,7 @@ static void printvar(const char *var)
static void list_vars(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -119,7 +120,7 @@ static void list_vars(void)
/* VAR <upsname> <varname> <val> */
if (numa < 4) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
printf("%s: %s\n", answer[2], answer[3]);
@ -129,7 +130,7 @@ static void list_vars(void)
static void list_upses(int verbose)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -151,7 +152,7 @@ static void list_upses(int verbose)
/* UPS <upsname> <description> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 3)", numa);
}
if(verbose) {
@ -165,7 +166,7 @@ static void list_upses(int verbose)
static void list_clients(const char *devname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -188,7 +189,7 @@ static void list_clients(const char *devname)
/* CLIENT <upsname> <address> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 3)", numa);
}
printf("%s\n", answer[2]);
@ -208,7 +209,8 @@ static void clean_exit(void)
int main(int argc, char **argv)
{
int i, port;
int i;
uint16_t port;
int varlist = 0, clientlist = 0, verbose = 0;
const char *prog = xbasename(argv[0]);
@ -218,7 +220,9 @@ int main(int argc, char **argv)
{
case 'L':
verbose = 1;
goto fallthrough_case_l;
case 'l':
fallthrough_case_l:
varlist = 1;
break;
case 'c':
@ -227,6 +231,9 @@ int main(int argc, char **argv)
case 'V':
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 */
#endif
case 'h':
default:

View file

@ -38,13 +38,14 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include "upsclient.h"
#include "common.h"
#include "nut_stdint.h"
#include "timehead.h"
#include "upsclient.h"
/* WA for Solaris/i386 bug: non-blocking connect sets errno to ENOENT */
#if (defined NUT_PLATFORM_SOLARIS && CPU_TYPE == i386)
#define SOLARIS_i386_NBCONNECT_ENOENT(status) (ENOENT == (status))
#if (defined NUT_PLATFORM_SOLARIS)
#define SOLARIS_i386_NBCONNECT_ENOENT(status) ( (!strcmp("i386", CPU_TYPE)) ? (ENOENT == (status)) : 0 )
#else
#define SOLARIS_i386_NBCONNECT_ENOENT(status) (0)
#endif /* end of Solaris/i386 WA for non-blocking connect */
@ -75,7 +76,7 @@
#define shutdown_how 2
#endif
struct {
static struct {
int flags;
const char *str;
} upscli_errlist[] =
@ -153,7 +154,7 @@ static char* nsscertpasswd = NULL;
static void ssl_debug(void)
{
int e;
unsigned long e;
char errmsg[SMALLBUF];
while ((e = ERR_get_error()) != 0) {
@ -162,32 +163,36 @@ static void ssl_debug(void)
}
}
static int ssl_error(SSL *ssl, int ret)
static int ssl_error(SSL *ssl, ssize_t ret)
{
int e;
e = SSL_get_error(ssl, ret);
if (ret >= INT_MAX) {
upslogx(LOG_ERR, "ssl_error() ret=%zd would not fit in an int", ret);
return -1;
}
e = SSL_get_error(ssl, (int)ret);
switch (e)
{
case SSL_ERROR_WANT_READ:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_WANT_READ", ret);
break;
case SSL_ERROR_WANT_WRITE:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_WRITE", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_WANT_WRITE", ret);
break;
case SSL_ERROR_SYSCALL:
if (ret == 0 && ERR_peek_error() == 0) {
upslogx(LOG_ERR, "ssl_error() EOF from client");
} else {
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_SYSCALL", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_SYSCALL", ret);
}
break;
default:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR %d", ret, e);
ssl_debug();
}
@ -199,6 +204,9 @@ static int ssl_error(SSL *ssl, int ret)
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
void *arg)
{
NUT_UNUSED_VARIABLE(retry);
NUT_UNUSED_VARIABLE(arg);
upslogx(LOG_INFO, "Intend to retrieve password for %s / %s: password %sconfigured",
PK11_GetSlotName(slot), PK11_GetTokenName(slot), nsscertpasswd?"":"not ");
return nsscertpasswd ? PL_strdup(nsscertpasswd) : NULL;
@ -233,6 +241,10 @@ static SECStatus AuthCertificateDontVerify(CERTCertDBHandle *arg, PRFileDesc *fd
PRBool checksig, PRBool isServer)
{
UPSCONN_t *ups = (UPSCONN_t *)SSL_RevealPinArg(fd);
NUT_UNUSED_VARIABLE(arg);
NUT_UNUSED_VARIABLE(checksig);
NUT_UNUSED_VARIABLE(isServer);
upslogx(LOG_INFO, "Do not intend to authenticate server %s",
ups?ups->host:"<unnamed>");
return SECSuccess;
@ -241,6 +253,8 @@ static SECStatus AuthCertificateDontVerify(CERTCertDBHandle *arg, PRFileDesc *fd
static SECStatus BadCertHandler(UPSCONN_t *arg, PRFileDesc *fd)
{
HOST_CERT_t* cert;
NUT_UNUSED_VARIABLE(fd);
upslogx(LOG_WARNING, "Certificate validation failed for %s",
(arg&&arg->host)?arg->host:"<unnamed>");
/* BadCertHandler is called when the NSS certificate validation is failed.
@ -288,6 +302,8 @@ static SECStatus GetClientAuthData(UPSCONN_t *arg, PRFileDesc *fd,
static void HandshakeCallback(PRFileDesc *fd, UPSCONN_t *client_data)
{
NUT_UNUSED_VARIABLE(fd);
upslogx(LOG_INFO, "SSL handshake done successfully with server %s",
client_data->host);
}
@ -298,17 +314,19 @@ int upscli_init(int certverify, const char *certpath,
const char *certname, const char *certpasswd)
{
#ifdef WITH_OPENSSL
int ret, ssl_mode = SSL_VERIFY_NONE;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const SSL_METHOD *ssl_method;
#else
SSL_METHOD *ssl_method;
#endif
long ret;
int ssl_mode = SSL_VERIFY_NONE;
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certpasswd);
#elif defined(WITH_NSS) /* WITH_OPENSSL */
SECStatus status;
#else
NUT_UNUSED_VARIABLE(certverify);
NUT_UNUSED_VARIABLE(certpath);
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certpasswd);
#endif /* WITH_OPENSSL | WITH_NSS */
if (upscli_initialized == 1) {
upslogx(LOG_WARNING, "upscli already initialized");
return -1;
@ -316,21 +334,31 @@ int upscli_init(int certverify, const char *certpath,
#ifdef WITH_OPENSSL
SSL_library_init();
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_load_error_strings();
SSL_library_init();
ssl_method = TLSv1_client_method();
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#else
ssl_ctx = SSL_CTX_new(TLS_client_method());
#endif
if (!ssl_method) {
return 0;
}
ssl_ctx = SSL_CTX_new(ssl_method);
if (!ssl_ctx) {
upslogx(LOG_ERR, "Can not initialize SSL context");
return -1;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* set minimum protocol TLSv1 */
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
#else
ret = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
if (ret != 1) {
upslogx(LOG_ERR, "Can not set minimum protocol to TLSv1");
return -1;
}
#endif
if (!certpath) {
if (certverify == 1) {
upslogx(LOG_ERR, "Can not verify certificate if any is specified");
@ -407,6 +435,11 @@ int upscli_init(int certverify, const char *certpath,
nsscertpasswd = xstrdup(certpasswd);
}
verify_certificate = certverify;
#else
/* Note: historically we do not return with error here,
* just fall through to below and treat as initialized.
*/
upslogx(LOG_ERR, "upscli_init called but SSL wasn't compiled in");
#endif /* WITH_OPENSSL | WITH_NSS */
upscli_initialized = 1;
@ -423,6 +456,11 @@ void upscli_add_host_cert(const char* hostname, const char* certname, int certve
cert->certverify = certverify;
cert->forcessl = forcessl;
first_host_cert = cert;
#else
NUT_UNUSED_VARIABLE(hostname);
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certverify);
NUT_UNUSED_VARIABLE(forcessl);
#endif /* WITH_NSS */
}
@ -438,11 +476,13 @@ static HOST_CERT_t* upscli_find_host_cert(const char* hostname)
cert = cert->next;
}
}
#else
NUT_UNUSED_VARIABLE(hostname);
#endif /* WITH_NSS */
return NULL;
}
int upscli_cleanup()
int upscli_cleanup(void)
{
#ifdef WITH_OPENSSL
if (ssl_ctx) {
@ -477,6 +517,16 @@ const char *upscli_strerror(UPSCONN_t *ups)
char sslbuf[UPSCLI_ERRBUF_LEN];
#endif
#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
if (!ups) {
return upscli_errlist[UPSCLI_ERR_INVALIDARG].str;
}
@ -534,6 +584,10 @@ const char *upscli_strerror(UPSCONN_t *ups)
return ups->errbuf;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
/* fallthrough */
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN, "Unknown error flag %d",
@ -545,9 +599,9 @@ const char *upscli_strerror(UPSCONN_t *ups)
/* Read up to buflen bytes from fd and return the number of bytes
read. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int upscli_select_read(const int fd, void *buf, const size_t buflen, const long d_sec, const long d_usec)
static ssize_t upscli_select_read(const int fd, void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
ssize_t ret;
fd_set fds;
struct timeval tv;
@ -566,17 +620,37 @@ static int upscli_select_read(const int fd, void *buf, const size_t buflen, cons
return read(fd, buf, buflen);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* internal: abstract the SSL calls for the other functions */
static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
static ssize_t net_read(UPSCONN_t *ups, char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret = -1;
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_read(ups->ssl, buf, buflen);
/* SSL_* routines deal with int type for return and buflen
* We might need to window our I/O if we exceed 2GB (in
* 32-bit builds)... Not likely to exceed in 64-bit builds,
* but smaller systems with 16-bits might be endangered :)
*/
assert(buflen <= INT_MAX);
int iret = SSL_read(ups->ssl, buf, (int)buflen);
assert(iret <= SSIZE_MAX);
ret = (ssize_t)iret;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Read(ups->ssl, buf, buflen);
/* PR_* routines deal in PRInt32 type
* We might need to window our I/O if we exceed 2GB :) */
assert(buflen <= PR_INT32_MAX);
ret = PR_Read(ups->ssl, buf, (PRInt32)buflen);
#endif /* WITH_OPENSSL | WITH_NSS*/
if (ret < 1) {
@ -587,7 +661,7 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
}
#endif
ret = upscli_select_read(ups->fd, buf, buflen, 5, 0);
ret = upscli_select_read(ups->fd, buf, buflen, timeout, 0);
/* error reading data, server disconnected? */
if (ret < 0) {
@ -602,13 +676,16 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
return ret;
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
/* Write up to buflen bytes to fd and return the number of bytes
written. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int upscli_select_write(const int fd, const void *buf, const size_t buflen, const long d_sec, const long d_usec)
static ssize_t upscli_select_write(const int fd, const void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
ssize_t ret;
fd_set fds;
struct timeval tv;
@ -627,17 +704,37 @@ static int upscli_select_write(const int fd, const void *buf, const size_t bufle
return write(fd, buf, buflen);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* internal: abstract the SSL calls for the other functions */
static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
static ssize_t net_write(UPSCONN_t *ups, const char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret = -1;
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_write(ups->ssl, buf, buflen);
/* SSL_* routines deal with int type for return and buflen
* We might need to window our I/O if we exceed 2GB (in
* 32-bit builds)... Not likely to exceed in 64-bit builds,
* but smaller systems with 16-bits might be endangered :)
*/
assert(buflen <= INT_MAX);
int iret = SSL_write(ups->ssl, buf, (int)buflen);
assert(iret <= SSIZE_MAX);
ret = (ssize_t)iret;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Write(ups->ssl, buf, buflen);
/* PR_* routines deal in PRInt32 type
* We might need to window our I/O if we exceed 2GB :) */
assert(buflen <= PR_INT32_MAX);
ret = PR_Write(ups->ssl, buf, (PRInt32)buflen);
#endif /* WITH_OPENSSL | WITH_NSS */
if (ret < 1) {
@ -648,7 +745,7 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
}
#endif
ret = upscli_select_write(ups->fd, buf, buflen, 0, 0);
ret = upscli_select_write(ups->fd, buf, buflen, timeout, 0);
/* error writing data, server disconnected? */
if (ret < 0) {
@ -663,6 +760,9 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
return ret;
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
#ifdef WITH_SSL
@ -737,7 +837,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
switch(res)
{
case 1:
upsdebugx(3, "SSL connected");
upsdebugx(3, "SSL connected (%s)", SSL_get_version(ups->ssl));
break;
case 0:
upslog_with_errno(1, "SSL_connect do not accept handshake.");
@ -840,12 +940,15 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
{
NUT_UNUSED_VARIABLE(ups);
NUT_UNUSED_VARIABLE(verifycert);
return 0; /* not supported */
}
#endif /* WITH_SSL */
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout)
int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags, struct timeval * timeout)
{
int sock_fd;
struct addrinfo hints, *res, *ai;
@ -871,7 +974,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
return -1;
}
snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port);
snprintf(sport, sizeof(sport), "%ju", (uintmax_t)port);
memset(&hints, 0, sizeof(hints));
@ -1019,24 +1122,24 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
if (tryssl || forcessl) {
ret = upscli_sslinit(ups, certverify);
if (forcessl && ret != 1) {
upslogx(LOG_ERR, "Can not connect to %s in SSL, disconnect", host);
upslogx(LOG_ERR, "Can not connect to NUT server %s in SSL, disconnect", host);
ups->upserror = UPSCLI_ERR_SSLFAIL;
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == -1) {
upslogx(LOG_NOTICE, "Error while connecting to %s, disconnect", host);
upslogx(LOG_NOTICE, "Error while connecting to NUT server %s, disconnect", host);
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == 0) {
if (certverify != 0) {
upslogx(LOG_NOTICE, "Can not connect to %s in SSL and "
upslogx(LOG_NOTICE, "Can not connect to NUT server %s in SSL and "
"certificate is needed, disconnect", host);
upscli_disconnect(ups);
return -1;
}
upsdebugx(3, "Can not connect to %s in SSL, continue uncrypted", host);
upsdebugx(3, "Can not connect to NUT server %s in SSL, continue unencrypted", host);
} else {
upslogx(LOG_INFO, "Connected to %s in SSL", host);
upslogx(LOG_INFO, "Connected to NUT server %s in SSL", host);
if (certverify == 0) {
/* you REALLY should set CERTVERIFY to 1 if using SSL... */
upslogx(LOG_WARNING, "Certificate verification is disabled");
@ -1047,7 +1150,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
return 0;
}
int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags)
int upscli_connect(UPSCONN_t *ups, const char *host, uint16_t port, int flags)
{
return upscli_tryconnect(ups,host,port,flags,NULL);
}
@ -1120,9 +1223,9 @@ static int upscli_errcheck(UPSCONN_t *ups, char *buf)
}
static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
int numarg, const char **arg)
size_t numarg, const char **arg)
{
int i;
size_t i;
size_t len;
char enc[UPSCLI_NETBUF_LEN];
const char *format;
@ -1142,8 +1245,20 @@ static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
/* snprintfcat would tie us to common */
len = strlen(buf);
#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
snprintf(buf + len, bufsize - len, format,
pconf_encode(arg[i], enc, sizeof(enc)));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
len = strlen(buf);
@ -1151,9 +1266,9 @@ static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
}
/* make sure upsd is giving us what we asked for */
static int verify_resp(int num, const char **q, char **a)
static int verify_resp(size_t num, const char **q, char **a)
{
int i;
size_t i;
for (i = 0; i < num; i++) {
if (strcasecmp(q[i], a[i]) != 0) {
@ -1166,8 +1281,8 @@ static int verify_resp(int num, const char **q, char **a)
return 1; /* OK */
}
int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer)
int upscli_get(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer)
{
char cmd[UPSCLI_NETBUF_LEN], tmp[UPSCLI_NETBUF_LEN];
@ -1219,7 +1334,7 @@ int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
return 0;
}
int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query)
int upscli_list_start(UPSCONN_t *ups, size_t numq, const char **query)
{
char cmd[UPSCLI_NETBUF_LEN], tmp[UPSCLI_NETBUF_LEN];
@ -1277,8 +1392,8 @@ int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query)
return 0;
}
int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer)
int upscli_list_next(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer)
{
char tmp[UPSCLI_NETBUF_LEN];
@ -1326,9 +1441,9 @@ int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
return 1;
}
int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
ssize_t upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret;
if (!ups) {
return -1;
@ -1349,7 +1464,7 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
return -1;
}
ret = net_write(ups, buf, buflen);
ret = net_write(ups, buf, buflen, timeout);
if (ret < 1) {
upscli_disconnect(ups);
@ -1359,9 +1474,14 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
return 0;
}
int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
ssize_t upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
{
int ret;
return upscli_sendline_timeout(ups, buf, buflen, 0);
}
ssize_t upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, const time_t timeout)
{
ssize_t ret;
size_t recv;
if (!ups) {
@ -1387,14 +1507,17 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
if (ups->readidx == ups->readlen) {
ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf));
ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf), timeout);
if (ret < 1) {
upscli_disconnect(ups);
return -1;
}
ups->readlen = ret;
/* Here ret is safe to cast since it is >=1 and certainly
* fits under SIZE_MAX being it signed sibling
*/
ups->readlen = (size_t)ret;
ups->readidx = 0;
}
@ -1409,8 +1532,13 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
return 0;
}
ssize_t upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
{
return upscli_readline_timeout(ups, buf, buflen, DEFAULT_NETWORK_TIMEOUT);
}
/* split upsname[@hostname[:port]] into separate components */
int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port)
int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t *port)
{
char *s, tmp[SMALLBUF], *last = NULL;
@ -1446,9 +1574,10 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port
}
/* split hostname[:port] into separate components */
int upscli_splitaddr(const char *buf, char **hostname, int *port)
int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port)
{
char *s, tmp[SMALLBUF], *last = NULL;
long l;
/* paranoia */
if ((!buf) || (!hostname) || (!port)) {
@ -1491,10 +1620,13 @@ int upscli_splitaddr(const char *buf, char **hostname, int *port)
}
}
if ((*(++s) == '\0') || ((*port = strtol(s, NULL, 10)) < 1 )) {
/* Check that "long" port fits in an "uint16_t" so is in IP range
* (under 65536) */
if ((*(++s) == '\0') || ((l = strtol(s, NULL, 10)) < 1 ) || (l > 65535)) {
fprintf(stderr, "upscli_splitaddr: no port specified after ':' separator\n");
return -1;
}
*port = (uint16_t)l;
return 0;
}
@ -1518,7 +1650,7 @@ int upscli_disconnect(UPSCONN_t *ups)
return 0;
}
net_write(ups, "LOGOUT\n", 7);
net_write(ups, "LOGOUT\n", 7, 0);
#ifdef WITH_OPENSSL
if (ups->ssl) {

View file

@ -28,6 +28,19 @@
#include <ssl.h>
#endif /* WITH_OPENSSL | WITH_NSS */
/* Not including nut_stdint.h because this is part of end-user API */
#if defined HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#if defined HAVE_STDINT_H
#include <stdint.h>
#endif
#if defined HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
@ -41,7 +54,7 @@ extern "C" {
typedef struct {
char *host;
int port;
uint16_t port;
int fd;
int flags;
int upserror;
@ -69,31 +82,33 @@ typedef struct {
const char *upscli_strerror(UPSCONN_t *ups);
int upscli_init(int certverify, const char *certpath, const char *certname, const char *certpasswd);
int upscli_cleanup();
int upscli_cleanup(void);
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags, struct timeval *tv);
int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags);
int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags, struct timeval *tv);
int upscli_connect(UPSCONN_t *ups, const char *host, uint16_t port, int flags);
void upscli_add_host_cert(const char* hostname, const char* certname, int certverify, int forcessl);
/* --- functions that only use the new names --- */
int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer);
int upscli_get(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer);
int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query);
int upscli_list_start(UPSCONN_t *ups, size_t numq, const char **query);
int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer);
int upscli_list_next(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer);
int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen);
ssize_t upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, const time_t timeout);
ssize_t upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen);
int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen);
ssize_t upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, const time_t timeout);
ssize_t upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen);
int upscli_splitname(const char *buf, char **upsname, char **hostname,
int *port);
uint16_t *port);
int upscli_splitaddr(const char *buf, char **hostname, int *port);
int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port);
int upscli_disconnect(UPSCONN_t *ups);

View file

@ -1,6 +1,8 @@
/* upscmd - simple "client" to test instant commands via upsd
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
Copyright (C)
2000 Russell Kroll <rkroll@exploits.org>
2019 EATON (author: Arnaud Quette <ArnaudQuette@eaton.com>)
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
@ -26,10 +28,13 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
static char *upsname = NULL, *hostname = NULL;
static UPSCONN_t *ups = NULL;
static int tracking_enabled = 0;
static unsigned int timeout = DEFAULT_TRACKING_TIMEOUT;
struct list_t {
char *name;
@ -41,13 +46,16 @@ static void usage(const char *prog)
printf("Network UPS Tools upscmd %s\n\n", UPS_VERSION);
printf("usage: %s [-h]\n", prog);
printf(" %s [-l <ups>]\n", prog);
printf(" %s [-u <username>] [-p <password>] <ups> <command> [<value>]\n\n", prog);
printf(" %s [-u <username>] [-p <password>] [-w] [-t <timeout>] <ups> <command> [<value>]\n\n", prog);
printf("Administration program to initiate instant commands on UPS hardware.\n");
printf("\n");
printf(" -h display this help text\n");
printf(" -l <ups> show available commands on UPS <ups>\n");
printf(" -u <username> set username for command authentication\n");
printf(" -p <password> set password for command authentication\n");
printf(" -w wait for the completion of command by the driver\n");
printf(" and return its actual result from the device\n");
printf(" -t <timeout> set a timeout when using -w (in seconds, default: %u)\n", DEFAULT_TRACKING_TIMEOUT);
printf("\n");
printf(" <ups> UPS identifier - <upsname>[@<hostname>[:<port>]]\n");
printf(" <command> Valid instant command - test.panel.start, etc.\n");
@ -57,7 +65,7 @@ static void usage(const char *prog)
static void print_cmd(char *cmdname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -80,7 +88,7 @@ static void print_cmd(char *cmdname)
static void listcmds(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
struct list_t *lhead = NULL, *llast = NULL, *ltmp, *lnext;
@ -105,7 +113,7 @@ static void listcmds(void)
/* CMD <upsname> <cmdname> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 3)", numa);
}
/* we must first read the entire list of commands,
@ -136,9 +144,21 @@ static void listcmds(void)
}
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
static void do_cmd(char **argv, const int argc)
{
int cmd_complete = 0;
char buf[SMALLBUF];
char tracking_id[UUID4_LEN];
time_t start, now;
if (argc > 1) {
snprintf(buf, sizeof(buf), "INSTCMD %s %s %s\n", upsname, argv[0], argv[1]);
@ -154,13 +174,88 @@ static void do_cmd(char **argv, const int argc)
fatalx(EXIT_FAILURE, "Instant command failed: %s", upscli_strerror(ups));
}
/* FUTURE: status cookies will tie in here */
/* verify answer */
if (strncmp(buf, "OK", 2) != 0) {
fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf);
}
/* check for status tracking id */
if (
!tracking_enabled ||
/* sanity check on the size: "OK TRACKING " + UUID4_LEN */
strlen(buf) != (UUID4_LEN - 1 + strlen("OK TRACKING "))
) {
/* reply as usual */
fprintf(stderr, "%s\n", buf);
return;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic ignored "-Wformat-truncation"
#endif
/* From the check above, we know that we have exactly UUID4_LEN chars
* (aka sizeof(tracking_id)) in the buf after "OK TRACKING " prefix,
* plus the null-byte.
*/
assert (UUID4_LEN == 1 + snprintf(tracking_id, sizeof(tracking_id), "%s", buf + strlen("OK TRACKING ")));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic pop
#endif
time(&start);
/* send status tracking request, looping if status is PENDING */
while (!cmd_complete) {
/* check for timeout */
time(&now);
if (difftime(now, start) >= timeout)
fatalx(EXIT_FAILURE, "Can't receive status tracking information: timeout");
snprintf(buf, sizeof(buf), "GET TRACKING %s\n", tracking_id);
if (upscli_sendline(ups, buf, strlen(buf)) < 0)
fatalx(EXIT_FAILURE, "Can't send status tracking request: %s", upscli_strerror(ups));
#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) )
/* Note for gating macros above: unsuffixed HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP
* means support of contexts both inside and outside function body, so the push
* above and pop below (outside this finction) are not used.
*/
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
/* Note that the individual warning pragmas for use inside function bodies
* are named without a _INSIDEFUNC suffix, for simplicity and legacy reasons
*/
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* and get status tracking reply */
assert(timeout < LONG_MAX);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic pop
#endif
if (upscli_readline_timeout(ups, buf, sizeof(buf), (long)timeout) < 0)
fatalx(EXIT_FAILURE, "Can't receive status tracking information: %s", upscli_strerror(ups));
if (strncmp(buf, "PENDING", 7))
cmd_complete = 1;
else
/* wait a second before retrying */
sleep(1);
}
fprintf(stderr, "%s\n", buf);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
static void clean_exit(void)
{
@ -175,12 +270,14 @@ static void clean_exit(void)
int main(int argc, char **argv)
{
int i, ret, port;
int i;
uint16_t port;
ssize_t ret;
int have_un = 0, have_pw = 0, cmdlist = 0;
char buf[SMALLBUF], username[SMALLBUF], password[SMALLBUF];
char buf[SMALLBUF * 2], username[SMALLBUF], password[SMALLBUF];
const char *prog = xbasename(argv[0]);
while ((i = getopt(argc, argv, "+lhu:p:V")) != -1) {
while ((i = getopt(argc, argv, "+lhu:p:t:wV")) != -1) {
switch (i)
{
@ -198,8 +295,20 @@ int main(int argc, char **argv)
have_pw = 1;
break;
case 't':
if (!str_to_uint(optarg, &timeout, 10))
fatal_with_errno(EXIT_FAILURE, "Could not convert the provided value for timeout ('-t' option) to unsigned int");
break;
case 'w':
tracking_enabled = 1;
break;
case 'V':
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 */
#endif
case 'h':
default:
@ -313,6 +422,25 @@ int main(int argc, char **argv)
fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups));
}
/* enable status tracking ID */
if (tracking_enabled) {
snprintf(buf, sizeof(buf), "SET TRACKING ON\n");
if (upscli_sendline(ups, buf, strlen(buf)) < 0) {
fatalx(EXIT_FAILURE, "Can't enable command status tracking: %s", upscli_strerror(ups));
}
if (upscli_readline(ups, buf, sizeof(buf)) < 0) {
fatalx(EXIT_FAILURE, "Enabling command status tracking failed: %s", upscli_strerror(ups));
}
/* Verify the result */
if (strncmp(buf, "OK", 2) != 0) {
fatalx(EXIT_FAILURE, "Enabling command status tracking failed. upsd answered: %s", buf);
}
}
do_cmd(&argv[1], argc - 1);
exit(EXIT_SUCCESS);

View file

@ -37,6 +37,7 @@
*/
#include "common.h"
#include "nut_stdint.h"
#include "upsclient.h"
#include "cgilib.h"
#include <stdlib.h>
@ -49,7 +50,7 @@
static char *monhost = NULL, *cmd = NULL;
static int port;
static uint16_t port;
static char *upsname, *hostname;
static UPSCONN_t ups;
@ -60,7 +61,7 @@ static UPSCONN_t ups;
void parsearg(char *var, char *value)
{
int i, v;
long long i, v; /* Be big enough to fit all expected inputs; truncate later */
/* avoid bogus junk from evil people */
if ((strlen(var) > MAX_CGI_STRLEN) || (strlen(value) > MAX_CGI_STRLEN))
@ -82,17 +83,20 @@ void parsearg(char *var, char *value)
for (i = 0; imgarg[i].name != NULL; i++) {
if (!strcmp(imgarg[i].name, var)) {
if (!strncmp(value, "0x", 2))
v = strtoul(value + 2, (char **)NULL, 16);
v = (long long)strtoul(value + 2, (char **)NULL, 16);
else
v = atoi(value);
v = (long long)atoi(value);
/* avoid false numbers from bad people */
if (v < imgarg[i].min)
imgarg[i].val = imgarg[i].min;
else if (v > imgarg[i].max)
imgarg[i].val = imgarg[i].max;
else
imgarg[i].val = v;
else {
assert (v < INT_MAX);
assert (v > INT_MIN);
imgarg[i].val = (int)v;
}
return;
}
}
@ -111,6 +115,9 @@ static int get_imgarg(const char *name)
}
/* write the HTML header then have gd dump the image */
static void drawimage(gdImagePtr im)
__attribute__((noreturn));
static void drawimage(gdImagePtr im)
{
printf("Pragma: no-cache\n");
@ -200,13 +207,25 @@ static void drawscale(
if (level % step10 == 0) {
y = scale_height * (lvlhi - level) / range;
snprintf(lbltxt, sizeof(lbltxt), "%d", level);
gdImageString(im, gdFontMediumBold, width - strlen(lbltxt)*gdFontMediumBold->w, y,
(unsigned char *) lbltxt, scale_num_color);
gdImageString(im, gdFontMediumBold,
width - (int)(strlen(lbltxt)) * gdFontMediumBold->w,
y, (unsigned char *) lbltxt, scale_num_color);
}
}
}
/* draws the bar style indicator */
static void drawbar(
int lvllo, int lvlhi, /* min and max numbers on the scale */
int step, int step5, int step10, /* steps for minor, submajor and major dashes */
int redlo1, int redhi1, /* first red zone start and end */
int redlo2, int redhi2, /* second red zone start and end */
int grnlo, int grnhi, /* green zone start and end */
double value, /* UPS variable value to draw */
const char *format /* printf style format to be used when rendering summary text */
)
__attribute__((noreturn));
static void drawbar(
int lvllo, int lvlhi, /* min and max numbers on the scale */
int step, int step5, int step10, /* steps for minor, submajor and major dashes */
@ -240,7 +259,7 @@ static void drawbar(
summary_color = color_alloc(im, get_imgarg("summary_col"));
/* rescale UPS value to fit in the scale */
bar_y = (1 - (value - lvllo) / (lvlhi - lvllo)) * scale_height;
bar_y = (int)((1.0 - (value - lvllo) / (lvlhi - lvllo)) * scale_height);
/* sanity checks: */
@ -257,9 +276,21 @@ static void drawbar(
bar_color);
/* stick the text version of the value at the bottom center */
#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
snprintf(text, sizeof(text), format, value);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
gdImageString(im, gdFontMediumBold,
(width - strlen(text)*gdFontMediumBold->w)/2,
(width - (int)(strlen(text))*gdFontMediumBold->w)/2,
height - gdFontMediumBold->h,
(unsigned char *) text, summary_color);
@ -269,6 +300,9 @@ static void drawbar(
}
/* draws the error image */
static void noimage(const char *fmt, ...)
__attribute__((noreturn));
static void noimage(const char *fmt, ...)
{
gdImagePtr im;
@ -278,7 +312,19 @@ static void noimage(const char *fmt, ...)
va_list ap;
va_start(ap, 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
vsnprintf(msg, sizeof(msg), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
width = get_imgarg("width");
@ -293,17 +339,23 @@ static void noimage(const char *fmt, ...)
if (width > height)
gdImageString(im, gdFontMediumBold,
(width - strlen(msg)*gdFontMediumBold->w)/2,
(width - (int)(strlen(msg))*gdFontMediumBold->w)/2,
(height - gdFontMediumBold->h)/2,
(unsigned char *) msg, summary_color);
else
gdImageStringUp(im, gdFontMediumBold,
(width - gdFontMediumBold->h)/2,
(height + strlen(msg)*gdFontMediumBold->w)/2,
(height + (int)(strlen(msg))*gdFontMediumBold->w)/2,
(unsigned char *) msg, summary_color);
drawimage(im);
/* NOTE: Earlier code called noimage() and then exit(EXIT_FAILURE);
* to signal an error via process exit code. Now that drawimage()
* always ends with exit(EXIT_SUCCESS) - which might make webserver
* feel good - the command-line use if any suffers no error returns.
*/
/* NOTREACHED */
}
@ -311,6 +363,10 @@ static void noimage(const char *fmt, ...)
UPS variable can be determined.
deviation < 0 means that values below nom should be grey instead of
green */
static void drawgeneralbar(double var, int min, int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void drawgeneralbar(double var, int min, int nom, int max,
int deviation, const char *format)
{
@ -370,6 +426,10 @@ static void drawgeneralbar(double var, int min, int nom, int max,
}
/* draws input and output voltage bar style indicators */
static void draw_utility(double var, int min, int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void draw_utility(double var, int min, int nom, int max,
int deviation, const char *format)
{
@ -405,7 +465,7 @@ static void draw_utility(double var, int min, int nom, int max,
/* Acceptable range of voltage is 85%-110% of nominal voltage
* in EU at least. Be conservative and say +-10% */
deviation = nom*0.1;
deviation = (int)(nom * 0.1);
drawgeneralbar(var, min, nom, max, deviation, format);
@ -413,9 +473,17 @@ static void draw_utility(double var, int min, int nom, int max,
}
/* draws battery.percent bar style indicator */
static void draw_battpct(double var, int min, int nom, int max,
int deviation, const char *format)
static void draw_battpct(double var, int min, int nom,
int max, int deviation, const char *format)
__attribute__((noreturn));
static void draw_battpct(double var, int min, int nom,
int max, int deviation, const char *format)
{
NUT_UNUSED_VARIABLE(nom);
NUT_UNUSED_VARIABLE(max);
NUT_UNUSED_VARIABLE(deviation);
if (min < 0) {
min = 50;
}
@ -424,6 +492,10 @@ static void draw_battpct(double var, int min, int nom, int max,
}
/* draws battery.voltage bar style indicator */
static void draw_battvolt(double var, int min, int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void draw_battvolt(double var, int min, int nom, int max,
int deviation, const char *format)
{
@ -450,18 +522,17 @@ static void draw_battvolt(double var, int min, int nom, int max,
}
if(min == -1) {
min = nom/2*1.6+1; /* Assume a 2V cell is dead at 1.6V */
min = (int)(nom/2*1.6+1); /* Assume a 2V cell is dead at 1.6V */
}
if(max == -1) {
max = nom/2*2.3+1; /* Assume 2.3V float charge voltage */
max = (int)(nom/2*2.3+1); /* Assume 2.3V float charge voltage */
}
if (nom < min || nom > max)
nom = -1;
deviation = -(nom*0.05); /* 5% deviation from nominal voltage */
deviation = (int)(-nom*0.05); /* 5% deviation from nominal voltage */
if(deviation==0) {
deviation = -1;
}
@ -470,33 +541,57 @@ static void draw_battvolt(double var, int min, int nom, int max,
}
/* draws ups.load bar style indicator */
static void draw_upsload(double var, int min, int nom, int max,
static void draw_upsload(double var, int min,
int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void draw_upsload(double var, int min,
int nom, int max,
int deviation, const char *format)
{
NUT_UNUSED_VARIABLE(min);
NUT_UNUSED_VARIABLE(nom);
NUT_UNUSED_VARIABLE(max);
NUT_UNUSED_VARIABLE(deviation);
drawbar(0, 125, 5, 5, 25, 100, 125, -1, -1, 0, 50, var, format);
}
/* draws temperature bar style indicator */
static void draw_temperature(double var, int min, int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void draw_temperature(double var, int min, int nom, int max,
int deviation, const char *format)
{
int hi = get_imgarg("tempmax");
int lo = get_imgarg("tempmin");
NUT_UNUSED_VARIABLE(nom);
NUT_UNUSED_VARIABLE(deviation);
drawbar(lo, hi, 1, 5, 10, lo, min, max, hi, -1, -1, var, format);
}
/* draws humidity bar style indicator */
static void draw_humidity(double var, int min, int nom, int max,
int deviation, const char *format)
__attribute__((noreturn));
static void draw_humidity(double var, int min, int nom, int max,
int deviation, const char *format)
{
NUT_UNUSED_VARIABLE(nom);
NUT_UNUSED_VARIABLE(deviation);
drawbar(0, 100, 2, 10, 20, 0, min, max, 100, -1, -1, var, format);
}
static int get_var(const char *var, char *buf, size_t buflen)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -523,6 +618,8 @@ int main(int argc, char **argv)
char str[SMALLBUF];
int i, min, nom, max;
double var = 0;
NUT_UNUSED_VARIABLE(argc);
NUT_UNUSED_VARIABLE(argv);
extractcgiargs();
@ -537,13 +634,17 @@ int main(int argc, char **argv)
if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) {
noimage("Invalid UPS definition (upsname[@hostname[:port]])\n");
exit(EXIT_FAILURE);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
}
if (upscli_connect(&ups, hostname, port, 0) < 0) {
noimage("Can't connect to server:\n%s\n",
upscli_strerror(&ups));
exit(EXIT_FAILURE);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
}
for (i = 0; imgvar[i].name; i++)
@ -553,7 +654,9 @@ int main(int argc, char **argv)
registered with this variable */
if (!imgvar[i].drawfunc) {
noimage("Draw function N/A");
exit(EXIT_FAILURE);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
}
/* get the variable value */
@ -564,7 +667,9 @@ int main(int argc, char **argv)
snprintf(str, sizeof(str), "%s N/A",
imgvar[i].name);
noimage(str);
exit(EXIT_FAILURE);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
}
/* when getting minimum, nominal and maximum values,
@ -617,7 +722,9 @@ int main(int argc, char **argv)
}
noimage("Unknown display");
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE);
#endif
}
imgvar_t imgvar[] = {

View file

@ -17,13 +17,20 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_UPSIMAGEARG_H_SEEN
#define NUT_UPSIMAGEARG_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
struct {
/* This is used in upsstats.c and in upsimage.c, but compiler complains about
* non-extern definition if this is not "static". To move or not to move?..
* Do we have cases of building binaries refering to only one of those objects?
*/
static struct {
char *name;
int val; /* hex digits, ala HTML */
int min; /* minimum reasonable value */
@ -71,3 +78,4 @@ extern imgvar_t imgvar[];
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSIMAGEARG_H_SEEN */

View file

@ -37,9 +37,11 @@
#include "config.h"
#include "timehead.h"
#include "nut_stdint.h"
#include "upslog.h"
static int port, reopen_flag = 0, exit_flag = 0;
static int reopen_flag = 0, exit_flag = 0;
static uint16_t port;
static char *upsname, *hostname;
static UPSCONN_t ups;
@ -79,6 +81,8 @@ static void set_exit_flag(int sig)
static void set_print_now_flag(int sig)
{
NUT_UNUSED_VARIABLE(sig);
/* no need to do anything, the signal will cause sleep to be interrupted */
}
@ -108,6 +112,9 @@ static void setup_signals(void)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGUSR1 handler");
}
static void help(const char *prog)
__attribute__((noreturn));
static void help(const char *prog)
{
printf("UPS status logger.\n");
@ -118,7 +125,9 @@ static void help(const char *prog)
printf(" -f <format> - Log format. See below for details.\n");
printf(" - Use -f \"<format>\" so your shell doesn't break it up.\n");
printf(" -i <interval> - Time between updates, in seconds\n");
printf(" -l <logfile> - Log file name, or - for stdout\n");
printf(" -l <logfile> - Log file name, or - for stdout (foreground by default)\n");
printf(" -F - stay foregrounded even if logging into a file\n");
printf(" -B - stay backgrounded even if logging to stdout\n");
printf(" -p <pidbase> - Base name for PID file (defaults to \"%s\")\n", prog);
printf(" -s <ups> - Monitor UPS <ups> - <upsname>@<host>[:<port>]\n");
printf(" - Example: -s myups@server\n");
@ -146,6 +155,7 @@ static void do_host(const char *arg)
{
int ret;
char hn[LARGEBUF];
NUT_UNUSED_VARIABLE(arg);
ret = gethostname(hn, sizeof(hn));
@ -159,11 +169,15 @@ static void do_host(const char *arg)
static void do_upshost(const char *arg)
{
NUT_UNUSED_VARIABLE(arg);
snprintfcat(logbuffer, sizeof(logbuffer), "%s", monhost);
}
static void do_pid(const char *arg)
{
NUT_UNUSED_VARIABLE(arg);
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (long)getpid());
}
@ -172,6 +186,7 @@ static void do_time(const char *arg)
unsigned int i;
char timebuf[SMALLBUF], *format;
time_t tod;
struct tm tmbuf;
format = xstrdup(arg);
@ -181,7 +196,7 @@ static void do_time(const char *arg)
format[i] = '%';
time(&tod);
strftime(timebuf, sizeof(timebuf), format, localtime(&tod));
strftime(timebuf, sizeof(timebuf), format, localtime_r(&tod, &tmbuf));
snprintfcat(logbuffer, sizeof(logbuffer), "%s", timebuf);
@ -191,7 +206,7 @@ static void do_time(const char *arg)
static void getvar(const char *var)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -235,6 +250,7 @@ static void do_var(const char *arg)
static void do_etime(const char *arg)
{
time_t tod;
NUT_UNUSED_VARIABLE(arg);
time(&tod);
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (unsigned long) tod);
@ -277,8 +293,9 @@ static void add_call(void (*fptr)(const char *arg), const char *arg)
/* turn the format string into a list of function calls with args */
static void compile_format(void)
{
unsigned int i;
int j, found, ofs;
size_t i;
int j, found;
size_t ofs;
char *cmd, *arg, *ptr;
for (i = 0; i < strlen(logformat); i++) {
@ -378,7 +395,7 @@ static void run_flist(void)
int main(int argc, char **argv)
{
int interval = 30, i;
int interval = 30, i, foreground = -1;
const char *prog = xbasename(argv[0]);
time_t now, nextpoll = 0;
const char *user = NULL;
@ -390,11 +407,13 @@ int main(int argc, char **argv)
printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) {
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FB")) != -1) {
switch(i) {
case 'h':
help(prog);
#ifndef HAVE___ATTRIBUTE__NORETURN
break;
#endif
case 's':
monhost = optarg;
@ -422,6 +441,14 @@ int main(int argc, char **argv)
case 'p':
pidfilebase = optarg;
break;
case 'F':
foreground = 1;
break;
case 'B':
foreground = 0;
break;
}
}
@ -486,8 +513,17 @@ int main(int argc, char **argv)
open_syslog(prog);
if (logfile != stdout)
if (foreground < 0) {
if (logfile == stdout) {
foreground = 1;
} else {
foreground = 0;
}
}
if (!foreground) {
background();
}
setup_signals();
@ -502,7 +538,7 @@ int main(int argc, char **argv)
if (nextpoll > now) {
/* there is still time left, so sleep it off */
sleep(difftime(nextpoll, now));
sleep((unsigned int)(difftime(nextpoll, now)));
nextpoll += interval;
} else {
/* we spent more time in polling than the interval allows */

View file

@ -1,5 +1,8 @@
/* upslog.h - table of functions for handling various logging functions */
#ifndef NUT_UPSLOG_H_SEEN
#define NUT_UPSLOG_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
@ -20,7 +23,10 @@ static void do_time(const char *arg);
static void do_var(const char *arg);
static void do_etime(const char *arg);
struct {
/* This is only used in upslog.c, but refers to routines declared here...
* To move or not to move?..
*/
static struct {
const char *name;
void (*func)(const char *arg);
} logcmds[] =
@ -31,7 +37,7 @@ struct {
{ "TIME", do_time },
{ "VAR", do_var },
{ "ETIME", do_etime },
{ NULL, (void(*)())(NULL) }
{ NULL, (void(*)(const char*))(NULL) }
};
#ifdef __cplusplus
@ -40,3 +46,4 @@ struct {
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSLOG_H_SEEN */

View file

@ -24,7 +24,10 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include "nut_stdint.h"
#include "upsclient.h"
#include "upsmon.h"
#include "parseconf.h"
@ -37,16 +40,19 @@
static char *shutdowncmd = NULL, *notifycmd = NULL;
static char *powerdownflag = NULL, *configfile = NULL;
static int minsupplies = 1, sleepval = 5, deadtime = 15;
/* default polling interval = 5 sec */
static int pollfreq = 5, pollfreqalert = 5;
/* slave hosts are given 15 sec by default to logout from upsd */
static int hostsync = 15;
static unsigned int minsupplies = 1, sleepval = 5;
/* sum of all power values from config file */
static int totalpv = 0;
static unsigned int totalpv = 0;
/* default TTL of a device gone AWOL, 3 x polling interval = 15 sec */
static int deadtime = 15;
/* default polling interval = 5 sec */
static unsigned int pollfreq = 5, pollfreqalert = 5;
/* secondary hosts are given 15 sec by default to logout from upsd */
static int hostsync = 15;
/* default replace battery warning interval (seconds) */
static int rbwarntime = 43200;
@ -55,7 +61,7 @@ static int rbwarntime = 43200;
static int nocommwarntime = 300;
/* default interval between the shutdown warning and the shutdown */
static int finaldelay = 5;
static unsigned int finaldelay = 5;
/* set by SIGHUP handler, cleared after reload finishes */
static int reload_flag = 0;
@ -83,6 +89,14 @@ static int opt_af = AF_UNSPEC;
static struct sigaction sa;
static sigset_t nut_upsmon_sigmask;
/* 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,
* to set the minimal debug level (CLI provided value less
* than that would not have effect, can only have more).
*/
static int nut_debug_level_global = -1;
static void setflag(int *val, int flag)
{
*val |= flag;
@ -173,8 +187,21 @@ static void do_notify(const utype_t *ups, int ntype)
if (notifylist[i].type == ntype) {
upsdebugx(2, "%s: ntype 0x%04x (%s)", __func__, ntype,
notifylist[i].name);
snprintf(msg, sizeof(msg), notifylist[i].msg ? notifylist[i].msg : notifylist[i].stockmsg,
#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
snprintf(msg, sizeof(msg),
notifylist[i].msg ? notifylist[i].msg : notifylist[i].stockmsg,
ups ? ups->sys : "");
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
notify(msg, notifylist[i].flags, notifylist[i].name,
upsname);
return;
@ -184,26 +211,40 @@ static void do_notify(const utype_t *ups, int ntype)
/* not found ?! */
}
/* check for master permissions on the server for this ups */
static int checkmaster(utype_t *ups)
/* check if we need "primary" mode (managerial permissions)
* on the server for this ups, and apply for them then.
* Returns 0 in case of error, 1 otherwise (including when
* we do not need to try becoming a primary). This currently
* propagates further as the return value of do_upsd_auth().
*/
/* TODO: Includes API change in NUT 2.8.0 to replace deprecated
* keywords "MASTER" with "PRIMARY", and "SLAVE" with "SECONDARY",
* (and backwards-compatible alias handling)
*/
static int apply_for_primary(utype_t *ups)
{
char buf[SMALLBUF];
char upscli_readraw_error;
/* don't bother if we're not configured as a master for this ups */
if (!flag_isset(ups->status, ST_MASTER))
/* don't bother if we're not configured as a primary for this ups */
if (!flag_isset(ups->status, ST_PRIMARY))
return 1;
/* this shouldn't happen (LOGIN checks it earlier) */
if ((ups->upsname == NULL) || (strlen(ups->upsname) == 0)) {
upslogx(LOG_ERR, "Set master on UPS [%s] failed: empty upsname",
upslogx(LOG_ERR, "Set primary managerial mode on UPS [%s] failed: empty upsname",
ups->sys);
return 0;
}
snprintf(buf, sizeof(buf), "MASTER %s\n", ups->upsname);
/* Use PRIMARY first but if talking to older server, retry with MASTER */
snprintf(buf, sizeof(buf), "PRIMARY %s\n", ups->upsname);
if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) {
upslogx(LOG_ALERT, "Can't set master mode on UPS [%s] - %s",
/* File descriptor not suitable, net_write() errors, etc.
* Not connected to issues with PRIMARY vs. MASTER keyword.
*/
upslogx(LOG_ALERT, "Can't set primary managerial mode on UPS [%s] - %s",
ups->sys, upscli_strerror(&ups->conn));
return 0;
}
@ -212,14 +253,41 @@ static int checkmaster(utype_t *ups)
if (!strncmp(buf, "OK", 2))
return 1;
/* not ERR, but not caught by readline either? */
/* Try the older keyword */
upsdebugx(3,
"%s: Server did not grant PRIMARY mode on UPS [%s], "
"retry with older MASTER keyword",
__func__, ups->upsname);
snprintf(buf, sizeof(buf), "MASTER %s\n", ups->upsname);
upslogx(LOG_ALERT, "Master privileges unavailable on UPS [%s]",
if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) {
upslogx(LOG_ALERT, "Can't set primary managerial mode on UPS [%s] - %s",
ups->sys, upscli_strerror(&ups->conn));
return 0;
}
if (upscli_readline(&ups->conn, buf, sizeof(buf)) == 0) {
if (!strncmp(buf, "OK", 2))
return 1;
upscli_readraw_error = 0;
}
else {
upscli_readraw_error = 1;
}
}
else {
upscli_readraw_error = 1;
}
if (upscli_readraw_error == 0) {
/* not ERR, but not caught by readline either? */
upslogx(LOG_ALERT, "Primary managerial privileges unavailable on UPS [%s]",
ups->sys);
upslogx(LOG_ALERT, "Response: [%s]", buf);
}
else { /* something caught by readraw's parsing call */
upslogx(LOG_ALERT, "Master privileges unavailable on UPS [%s]",
upslogx(LOG_ALERT, "Primary managerial privileges unavailable on UPS [%s]",
ups->sys);
upslogx(LOG_ALERT, "Reason: %s", upscli_strerror(&ups->conn));
}
@ -305,8 +373,8 @@ static int do_upsd_auth(utype_t *ups)
upsdebugx(1, "Logged into UPS %s", ups->sys);
setflag(&ups->status, ST_LOGIN);
/* now see if we also need to test master permissions */
return checkmaster(ups);
/* now see if we also need to test primary managerial-mode permissions */
return apply_for_primary(ups);
}
/* set flags and make announcements when a UPS has been checked successfully */
@ -417,9 +485,10 @@ static void set_pdflag(void)
/* the actual shutdown procedure */
static void doshutdown(void)
{
int ret;
__attribute__((noreturn));
static void doshutdown(void)
{
/* this should probably go away at some point */
upslogx(LOG_CRIT, "Executing automatic power-fail shutdown");
wall("Executing automatic power-fail shutdown\n");
@ -431,20 +500,25 @@ static void doshutdown(void)
/* in the pipe model, we let the parent do this for us */
if (use_pipe) {
char ch;
ssize_t wret;
ch = 1;
ret = write(pipefd[1], &ch, 1);
wret = write(pipefd[1], &ch, 1);
if (wret < 1)
upslogx(LOG_ERR, "Unable to call parent pipe for shutdown");
} else {
/* one process model = we do all the work here */
int sret;
if (geteuid() != 0)
upslogx(LOG_WARNING, "Not root, shutdown may fail");
set_pdflag();
ret = system(shutdowncmd);
sret = system(shutdowncmd);
if (ret != 0)
if (sret != 0)
upslogx(LOG_ERR, "Unable to call shutdown command: %s",
shutdowncmd);
}
@ -456,7 +530,7 @@ static void doshutdown(void)
static void setfsd(utype_t *ups)
{
char buf[SMALLBUF];
int ret;
ssize_t ret;
/* this shouldn't happen */
if (!ups->upsname) {
@ -499,14 +573,21 @@ static void set_alarm(void)
static void clear_alarm(void)
{
#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
signal(SIGALRM, SIG_IGN);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
# pragma GCC diagnostic pop
#endif
alarm(0);
}
static int get_var(utype_t *ups, const char *var, char *buf, size_t bufsize)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -557,7 +638,7 @@ static int get_var(utype_t *ups, const char *var, char *buf, size_t bufsize)
if (numa < numq) {
upslogx(LOG_ERR, "%s: Error: insufficient data "
"(got %d args, need at least %d)",
"(got %zu args, need at least %zu)",
var, numa, numq);
return -1;
}
@ -566,12 +647,16 @@ static int get_var(utype_t *ups, const char *var, char *buf, size_t bufsize)
return 0;
}
static void slavesync(void)
/* Called by upsmon which is the primary on some UPS(es) to wait
* until all secondaries log out from it on the shared upsd server
* or the HOSTSYNC timeout expires
*/
static void sync_secondaries(void)
{
utype_t *ups;
char temp[SMALLBUF];
time_t start, now;
int maxlogins, logins;
long maxlogins, logins;
time(&start);
@ -580,8 +665,8 @@ static void slavesync(void)
for (ups = firstups; ups != NULL; ups = ups->next) {
/* only check login count on our master(s) */
if (!flag_isset(ups->status, ST_MASTER))
/* only check login count on devices we are the primary for */
if (!flag_isset(ups->status, ST_PRIMARY))
continue;
set_alarm();
@ -596,11 +681,15 @@ static void slavesync(void)
clear_alarm();
}
/* if no UPS has more than 1 login (us), then slaves are gone */
/* if no UPS has more than 1 login (that would be us),
* then secondaries are all gone */
/* TO THINK: how about redundant setups with several primary-mode
* clients managing an UPS, or possibly differend UPSes, with the
* same upsd? */
if (maxlogins <= 1)
return;
/* after HOSTSYNC seconds, assume slaves are stuck and bail */
/* after HOSTSYNC seconds, assume secondaries are stuck - and bail */
time(&now);
if ((now - start) > hostsync) {
@ -612,31 +701,34 @@ static void slavesync(void)
}
}
static void forceshutdown(void)
__attribute__((noreturn));
static void forceshutdown(void)
{
utype_t *ups;
int isamaster = 0;
int isaprimary = 0;
upsdebugx(1, "Shutting down any UPSes in MASTER mode...");
upsdebugx(1, "Shutting down any UPSes in PRIMARY mode...");
/* set FSD on any "master" UPS entries (forced shutdown in progress) */
/* set FSD on any "primary" UPS entries (forced shutdown in progress) */
for (ups = firstups; ups != NULL; ups = ups->next)
if (flag_isset(ups->status, ST_MASTER)) {
isamaster = 1;
if (flag_isset(ups->status, ST_PRIMARY)) {
isaprimary = 1;
setfsd(ups);
}
/* if we're not a master on anything, we should shut down now */
if (!isamaster)
/* if we're not a primary on anything, we should shut down now */
if (!isaprimary)
doshutdown();
/* must be the master now */
upsdebugx(1, "This system is a master... waiting for slave logout...");
/* we must be the primary now */
upsdebugx(1, "This system is a primary... waiting for secondaries to logout...");
/* wait up to HOSTSYNC seconds for slaves to logout */
slavesync();
/* wait up to HOSTSYNC seconds for secondaries to logout */
sync_secondaries();
/* time expired or all the slaves are gone, so shutdown */
/* time expired or all the secondaries are gone, so shutdown */
doshutdown();
}
@ -644,7 +736,10 @@ static int is_ups_critical(utype_t *ups)
{
time_t now;
/* FSD = the master is forcing a shutdown */
/* FSD = the primary is forcing a shutdown, or a driver forwarded the flag
* from a smarter UPS depending on vendor protocol, ability and settings
* (e.g. is charging but battery too low to guarantee safety to the load)
*/
if (flag_isset(ups->status, ST_FSD))
return 1;
@ -655,24 +750,37 @@ static int is_ups_critical(utype_t *ups)
/* must be OB+LB now */
/* if we're a master, declare it critical so we set FSD on it */
if (flag_isset(ups->status, ST_MASTER))
/* if UPS is calibrating, don't declare it critical */
/* FIXME: Consider UPSes where we can know if they have other power
* circuits (bypass, etc.) and whether those do currently provide
* wall power to the host - and that we do not have both calibration
* and a real outage, when we still should shut down right now.
*/
if (flag_isset(ups->status, ST_CAL)) {
upslogx(LOG_WARNING, "%s: seems that UPS [%s] is OB+LB now, but "
"it is also calibrating - not declaring a critical state",
__func__, ups->upsname);
return 0;
}
/* if we're a primary, declare it critical so we set FSD on it */
if (flag_isset(ups->status, ST_PRIMARY))
return 1;
/* must be a slave now */
/* must be a secondary now */
/* FSD isn't set, so the master hasn't seen it yet */
/* FSD isn't set, so the primary hasn't seen it yet */
time(&now);
/* give the master up to HOSTSYNC seconds before shutting down */
/* give the primary up to HOSTSYNC seconds before shutting down */
if ((now - ups->lastnoncrit) > hostsync) {
upslogx(LOG_WARNING, "Giving up on the master for UPS [%s]",
upslogx(LOG_WARNING, "Giving up on the primary for UPS [%s]",
ups->sys);
return 1;
}
/* there's still time left */
/* there's still time left, maybe OB+LB will go away next time we look? */
return 0;
}
@ -680,7 +788,7 @@ static int is_ups_critical(utype_t *ups)
static void recalc(void)
{
utype_t *ups;
int val_ol = 0;
unsigned int val_ol = 0;
time_t now;
time(&now);
@ -707,8 +815,8 @@ static void recalc(void)
ups = ups->next;
}
upsdebugx(3, "Current power value: %d", val_ol);
upsdebugx(3, "Minimum power value: %d", minsupplies);
upsdebugx(3, "Current power value: %u", val_ol);
upsdebugx(3, "Minimum power value: %u", minsupplies);
if (val_ol < minsupplies)
forceshutdown();
@ -741,6 +849,21 @@ static void upsreplbatt(utype_t *ups)
}
}
static void ups_cal(utype_t *ups)
{
if (flag_isset(ups->status, ST_CAL)) { /* no change */
upsdebugx(4, "%s: %s (no change)", __func__, ups->sys);
return;
}
upsdebugx(3, "%s: %s (first time)", __func__, ups->sys);
/* must have changed from !CAL to CAL, so notify */
do_notify(ups, NOTIFY_CAL);
setflag(&ups->status, ST_CAL);
}
static void ups_fsd(utype_t *ups)
{
if (flag_isset(ups->status, ST_FSD)) { /* no change */
@ -770,8 +893,8 @@ static void drop_connection(utype_t *ups)
}
/* change some UPS parameters during reloading */
static void redefine_ups(utype_t *ups, int pv, const char *un,
const char *pw, const char *master)
static void redefine_ups(utype_t *ups, unsigned int pv, const char *un,
const char *pw, const char *managerialOption)
{
ups->retain = 1;
@ -849,45 +972,75 @@ static void redefine_ups(utype_t *ups, int pv, const char *un,
}
}
/* slave -> master */
if ((!strcasecmp(master, "master")) && (!flag_isset(ups->status, ST_MASTER))) {
upslogx(LOG_INFO, "UPS [%s]: redefined as master", ups->sys);
setflag(&ups->status, ST_MASTER);
/* secondary|slave -> primary|master */
if ( ( (!strcasecmp(managerialOption, "primary"))
|| (!strcasecmp(managerialOption, "master")) )
&& (!flag_isset(ups->status, ST_PRIMARY)) ) {
upslogx(LOG_INFO, "UPS [%s]: redefined as a primary", ups->sys);
setflag(&ups->status, ST_PRIMARY);
/* reset connection to ensure master mode gets checked */
/* reset connection to ensure primary mode gets checked */
drop_connection(ups);
return;
}
/* master -> slave */
if ((!strcasecmp(master, "slave")) && (flag_isset(ups->status, ST_MASTER))) {
upslogx(LOG_INFO, "UPS [%s]: redefined as slave", ups->sys);
clearflag(&ups->status, ST_MASTER);
/* primary|master -> secondary|slave */
if ( ( (!strcasecmp(managerialOption, "secondary"))
|| (!strcasecmp(managerialOption, "slave")) )
&& (flag_isset(ups->status, ST_PRIMARY)) ) {
upslogx(LOG_INFO, "UPS [%s]: redefined as a secondary", ups->sys);
clearflag(&ups->status, ST_PRIMARY);
return;
}
}
static void addups(int reloading, const char *sys, const char *pvs,
const char *un, const char *pw, const char *master)
const char *un, const char *pw, const char *managerialOption)
{
int pv;
unsigned int pv;
utype_t *tmp, *last;
/* the username is now required - no more host-based auth */
if ((!sys) || (!pvs) || (!pw) || (!master) || (!un)) {
if ((!sys) || (!pvs) || (!pw) || (!managerialOption) || (!un)) {
upslogx(LOG_WARNING, "Ignoring invalid MONITOR line in %s!", configfile);
upslogx(LOG_WARNING, "MONITOR configuration directives require five arguments.");
return;
}
pv = strtol(pvs, (char **) NULL, 10);
long lpv = strtol(pvs, (char **) NULL, 10);
if (pv < 0) {
#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
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
# pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# pragma clang diagnostic ignored "-Wtautological-compare"
# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* Different platforms, different sizes, none fits all... */
if (lpv < 0 || (sizeof(long) > sizeof(unsigned int) && lpv > (long)UINT_MAX)) {
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#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 pop
#endif
upslogx(LOG_WARNING, "UPS [%s]: ignoring invalid power value [%s]",
sys, pvs);
return;
}
pv = (unsigned int)lpv;
last = tmp = firstups;
@ -897,7 +1050,7 @@ static void addups(int reloading, const char *sys, const char *pvs,
/* check for duplicates */
if (!strcmp(tmp->sys, sys)) {
if (reloading)
redefine_ups(tmp, pv, un, pw, master);
redefine_ups(tmp, pv, un, pw, managerialOption);
else
upslogx(LOG_WARNING, "Warning: ignoring duplicate"
" UPS [%s]", sys);
@ -914,10 +1067,7 @@ static void addups(int reloading, const char *sys, const char *pvs,
/* build this up so the user doesn't run with bad settings */
totalpv += tmp->pv;
if (un)
tmp->un = xstrdup(un);
else
tmp->un = NULL;
tmp->pw = xstrdup(pw);
tmp->status = 0;
@ -932,8 +1082,10 @@ static void addups(int reloading, const char *sys, const char *pvs,
tmp->lastrbwarn = 0;
tmp->lastncwarn = 0;
if (!strcasecmp(master, "master"))
setflag(&tmp->status, ST_MASTER);
if ( (!strcasecmp(managerialOption, "primary"))
|| (!strcasecmp(managerialOption, "master")) ) {
setflag(&tmp->status, ST_PRIMARY);
}
tmp->next = NULL;
@ -944,7 +1096,7 @@ static void addups(int reloading, const char *sys, const char *pvs,
if (tmp->pv)
upslogx(LOG_INFO, "UPS: %s (%s) (power value %d)", tmp->sys,
flag_isset(tmp->status, ST_MASTER) ? "master" : "slave",
flag_isset(tmp->status, ST_PRIMARY) ? "primary" : "secondary",
tmp->pv);
else
upslogx(LOG_INFO, "UPS: %s (monitoring only)", tmp->sys);
@ -1054,7 +1206,7 @@ static void checkmode(char *cfgentry, char *oldvalue, char *newvalue,
}
/* returns 1 if used, 0 if not, so we can complain about bogus configs */
static int parse_conf_arg(int numargs, char **arg)
static int parse_conf_arg(size_t numargs, char **arg)
{
/* using up to arg[1] below */
if (numargs < 2)
@ -1092,13 +1244,23 @@ static int parse_conf_arg(int numargs, char **arg)
/* POLLFREQ <num> */
if (!strcmp(arg[0], "POLLFREQ")) {
pollfreq = atoi(arg[1]);
int ipollfreq = atoi(arg[1]);
if (ipollfreq < 0) {
upsdebugx(0, "Ignoring invalid POLLFREQ value: %d", ipollfreq);
} else {
pollfreq = (unsigned int)ipollfreq;
}
return 1;
}
/* POLLFREQALERT <num> */
if (!strcmp(arg[0], "POLLFREQALERT")) {
pollfreqalert = atoi(arg[1]);
int ipollfreqalert = atoi(arg[1]);
if (ipollfreqalert < 0) {
upsdebugx(0, "Ignoring invalid POLLFREQALERT value: %d", ipollfreqalert);
} else {
pollfreqalert = (unsigned int)ipollfreqalert;
}
return 1;
}
@ -1116,7 +1278,12 @@ static int parse_conf_arg(int numargs, char **arg)
/* MINSUPPLIES <num> */
if (!strcmp(arg[0], "MINSUPPLIES")) {
minsupplies = atoi(arg[1]);
int iminsupplies = atoi(arg[1]);
if (iminsupplies < 0) {
upsdebugx(0, "Ignoring invalid MINSUPPLIES value: %d", iminsupplies);
} else {
minsupplies = (unsigned int)iminsupplies;
}
return 1;
}
@ -1134,7 +1301,12 @@ static int parse_conf_arg(int numargs, char **arg)
/* FINALDELAY <num> */
if (!strcmp(arg[0], "FINALDELAY")) {
finaldelay = atoi(arg[1]);
int ifinaldelay = atoi(arg[1]);
if (ifinaldelay < 0) {
upsdebugx(0, "Ignoring invalid FINALDELAY value: %d", ifinaldelay);
} else {
finaldelay = (unsigned int)ifinaldelay;
}
return 1;
}
@ -1164,6 +1336,18 @@ static int parse_conf_arg(int numargs, char **arg)
return 1;
}
/* DEBUG_MIN (NUM) */
/* debug_min (NUM) also acceptable, to be on par with ups.conf */
if (!strcasecmp(arg[0], "DEBUG_MIN")) {
int lvl = -1; // typeof common/common.c: int nut_debug_level
if ( str_to_int (arg[1], &lvl, 10) && lvl >= 0 ) {
nut_debug_level_global = lvl;
} else {
upslogx(LOG_INFO, "WARNING : Invalid DEBUG_MIN value found in upsmon.conf global settings");
}
return 1;
}
/* using up to arg[2] below */
if (numargs < 3)
return 0;
@ -1209,7 +1393,7 @@ static int parse_conf_arg(int numargs, char **arg)
fatalx(EXIT_FAILURE, "Fatal error: unusable configuration");
}
/* <sys> <pwrval> <user> <pw> ("master" | "slave") */
/* <sys> <pwrval> <user> <pw> ("primary"|"master" | "secondary"|"slave") */
addups(reload_flag, arg[1], arg[2], arg[3], arg[4], arg[5]);
return 1;
}
@ -1241,6 +1425,13 @@ static void loadconfig(void)
fatalx(EXIT_FAILURE, "%s", ctx.errmsg);
}
if (reload_flag == 1) {
/* if upsmon.conf added or changed
* (or commented away) the debug_min
* setting, detect that */
nut_debug_level_global = -1;
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
@ -1267,13 +1458,22 @@ static void loadconfig(void)
}
}
if (reload_flag == 1) {
if (nut_debug_level_global > -1) {
upslogx(LOG_INFO,
"Applying debug_min=%d from upsmon.conf",
nut_debug_level_global);
nut_debug_level = nut_debug_level_global;
}
}
pconf_finish(&ctx);
}
/* SIGPIPE handler */
static void sigpipe(int sig)
{
upsdebugx(1, "SIGPIPE: dazed and confused, but continuing...");
upsdebugx(1, "SIGPIPE: dazed and confused, but continuing after signal %i...", sig);
}
/* SIGQUIT, SIGTERM handler */
@ -1329,12 +1529,16 @@ static void user_fsd(int sig)
static void set_reload_flag(int sig)
{
NUT_UNUSED_VARIABLE(sig);
reload_flag = 1;
}
/* handler for alarm when getupsvarfd times out */
static void read_timeout(int sig)
{
NUT_UNUSED_VARIABLE(sig);
/* don't do anything here, just return */
}
@ -1370,9 +1574,10 @@ static void setup_signals(void)
/* remember the last time the ups was not critical (OB + LB) */
static void update_crittimer(utype_t *ups)
{
/* if !OB or !LB, then it's not critical, so log the time */
/* if !OB, !LB, or CAL, then it's not critical, so log the time */
if ((!flag_isset(ups->status, ST_ONBATT)) ||
(!flag_isset(ups->status, ST_LOWBATT))) {
(!flag_isset(ups->status, ST_LOWBATT)) ||
(flag_isset(ups->status, ST_CAL))) {
time(&ups->lastnoncrit);
return;
@ -1432,6 +1637,9 @@ static int try_connect(utype_t *ups)
/* we're definitely connected now */
setflag(&ups->status, ST_CONNECTED);
/* prevent connection leaking to NOTIFYCMD */
fcntl(upscli_fd(&ups->conn), F_SETFD, FD_CLOEXEC);
/* now try to authenticate to upsd */
ret = do_upsd_auth(ups);
@ -1456,7 +1664,7 @@ static void parse_status(utype_t *ups, char *status)
upsdebugx(2, "%s: [%s]", __func__, status);
/* empty response is the same as a dead ups */
if (!strcmp(status, "")) {
if (status == NULL || status[0] == '\0') {
ups_is_gone(ups);
return;
}
@ -1487,6 +1695,8 @@ static void parse_status(utype_t *ups, char *status)
ups_low_batt(ups);
if (!strcasecmp(statword, "RB"))
upsreplbatt(ups);
if (!strcasecmp(statword, "CAL"))
ups_cal(ups);
/* do it last to override any possible OL */
if (!strcasecmp(statword, "FSD"))
@ -1634,17 +1844,23 @@ static int check_pdflag(void)
return EXIT_SUCCESS;
}
static void help(const char *progname)
static void help(const char *arg_progname)
__attribute__((noreturn));
static void help(const char *arg_progname)
{
printf("Monitors UPS servers and may initiate shutdown if necessary.\n\n");
printf("usage: %s [OPTIONS]\n\n", progname);
printf("usage: %s [OPTIONS]\n\n", arg_progname);
printf(" -c <cmd> send command to running process\n");
printf(" commands:\n");
printf(" - fsd: shutdown all master UPSes (use with caution)\n");
printf(" - fsd: shutdown all primary-mode UPSes (use with caution)\n");
printf(" - reload: reread configuration\n");
printf(" - stop: stop monitoring and exit\n");
printf(" -D raise debugging level\n");
printf(" -P <pid> send the signal above to specified PID (bypassing PID file)\n");
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(" -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");
@ -1655,15 +1871,26 @@ static void help(const char *progname)
exit(EXIT_SUCCESS);
}
static void runparent(int fd)
__attribute__((noreturn));
static void runparent(int fd)
{
int ret;
ssize_t ret;
int sret;
char ch;
/* handling signals is the child's job */
#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
signal(SIGHUP, SIG_IGN);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
# pragma GCC diagnostic pop
#endif
ret = read(fd, &ch, 1);
@ -1680,9 +1907,9 @@ static void runparent(int fd)
/* have to do this here - child is unprivileged */
set_pdflag();
ret = system(shutdowncmd);
sret = system(shutdowncmd);
if (ret != 0)
if (sret != 0)
upslogx(LOG_ERR, "parent: Unable to call shutdown command: %s",
shutdowncmd);
@ -1710,10 +1937,15 @@ static void start_pipe(void)
close(pipefd[1]);
runparent(pipefd[0]);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* NOTREACHED */
#endif
}
close(pipefd[0]);
/* prevent pipe leaking to NOTIFYCMD */
fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
}
static void delete_ups(utype_t *target)
@ -1814,7 +2046,7 @@ static void reload_conf(void)
upslogx(LOG_CRIT, "Fatal error: total power value (%d) less "
"than MINSUPPLIES (%d)", totalpv, minsupplies);
fatalx(EXIT_FAILURE, "Impossible power configuation, unable to continue");
fatalx(EXIT_FAILURE, "Impossible power configuration, unable to continue");
}
/* finally clear the flag */
@ -1859,7 +2091,8 @@ static void check_parent(void)
int main(int argc, char *argv[])
{
const char *prog = xbasename(argv[0]);
int i, cmd = 0, checking_flag = 0;
int i, cmd = 0, cmdret = -1, checking_flag = 0, foreground = -1;
pid_t oldpid = -1;
printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);
@ -1870,7 +2103,7 @@ int main(int argc, char *argv[])
run_as_user = xstrdup(RUN_AS_USER);
while ((i = getopt(argc, argv, "+Dhic:f:pu:VK46")) != -1) {
while ((i = getopt(argc, argv, "+DFBhic:P:f:pu:VK46")) != -1) {
switch (i) {
case 'c':
if (!strncmp(optarg, "fsd", strlen(optarg)))
@ -1884,16 +2117,30 @@ int main(int argc, char *argv[])
if (cmd == 0)
help(argv[0]);
break;
case 'P':
if ((oldpid = parsepid(optarg)) < 0)
help(argv[0]);
break;
case 'D':
nut_debug_level++;
break;
case 'F':
foreground = 1;
break;
case 'B':
foreground = 0;
break;
case 'f':
free(configfile);
configfile = xstrdup(optarg);
break;
case 'h':
help(argv[0]);
#ifndef HAVE___ATTRIBUTE__NORETURN
break;
#endif
case 'K':
checking_flag = 1;
break;
@ -1915,22 +2162,56 @@ int main(int argc, char *argv[])
break;
default:
help(argv[0]);
#ifndef HAVE___ATTRIBUTE__NORETURN
break;
#endif
}
}
if (foreground < 0) {
if (nut_debug_level > 0) {
foreground = 1;
} else {
foreground = 0;
}
}
if (cmd) {
sendsignal(prog, cmd);
exit(EXIT_SUCCESS);
if (oldpid < 0) {
cmdret = sendsignal(prog, cmd);
} else {
cmdret = sendsignalpid(oldpid, cmd);
}
/* 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 <pid> 0') */
if (sendsignal(prog, 0) == 0) {
if (oldpid < 0) {
cmdret = sendsignal(prog, 0);
} else {
cmdret = sendsignalpid(oldpid, 0);
}
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);
case -3:
case -2:
upslogx(LOG_WARNING, "Could not %s PID file "
"to see if previous upsmon instance is "
"already running!\n",
(cmdret == -3 ? "find" : "parse"));
break;
case -1:
default:
/* Just failed to send signal, no competitor running */
break;
}
argc -= optind;
@ -1940,6 +2221,14 @@ int main(int argc, char *argv[])
loadconfig();
/* CLI debug level can not be smaller than debug_min specified
* in upsmon.conf. Note that non-zero debug_min does not impact
* foreground running mode.
*/
if (nut_debug_level_global > nut_debug_level)
nut_debug_level = nut_debug_level_global;
upsdebugx(1, "debug level is '%d'", nut_debug_level);
if (checking_flag)
exit(check_pdflag());
@ -1962,9 +2251,11 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
if (nut_debug_level < 1) {
if (!foreground) {
background();
} else {
}
if (nut_debug_level >= 1) {
upsdebugx(1, "debug level is '%d'", nut_debug_level);
}

View file

@ -17,15 +17,20 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_UPSMON_H_SEEN
#define NUT_UPSMON_H_SEEN 1
/* flags for ups->status */
#define ST_ONLINE (1 << 0) /* UPS is on line (OL) */
#define ST_ONBATT (1 << 1) /* UPS is on battery (OB) */
#define ST_LOWBATT (1 << 2) /* UPS has a low battery (LB) */
#define ST_FSD (1 << 3) /* master has set forced shutdown flag */
#define ST_MASTER (1 << 4) /* we are the master on this UPS */
#define ST_FSD (1 << 3) /* primary has set forced shutdown flag */
#define ST_PRIMARY (1 << 4) /* we are the primary (manager) of this UPS */
#define ST_MASTER ST_PRIMARY /* legacy alias */
#define ST_LOGIN (1 << 5) /* we are logged into this UPS */
#define ST_CONNECTED (1 << 6) /* upscli_connect returned OK */
#define ST_CAL (1 << 7) /* UPS calibration in progress (CAL) */
/* required contents of flag file */
#define SDMAGIC "upsmon-shutdown-file"
@ -44,9 +49,9 @@ typedef struct {
char *sys; /* raw system name from .conf */
char *upsname; /* just upsname */
char *hostname; /* just hostname */
int port; /* just the port */
uint16_t port; /* just the port */
int pv; /* power value from conf */
unsigned int pv; /* power value from conf */
char *un; /* username (optional for now) */
char *pw; /* password from conf */
int status; /* status (see flags above) */
@ -68,13 +73,14 @@ typedef struct {
#define NOTIFY_ONLINE 0 /* UPS went on-line */
#define NOTIFY_ONBATT 1 /* UPS went on battery */
#define NOTIFY_LOWBATT 2 /* UPS went to low battery */
#define NOTIFY_FSD 3 /* Master upsmon set FSD flag */
#define NOTIFY_FSD 3 /* Primary upsmon set FSD flag */
#define NOTIFY_COMMOK 4 /* Communication established */
#define NOTIFY_COMMBAD 5 /* Communication lost */
#define NOTIFY_SHUTDOWN 6 /* System shutdown in progress */
#define NOTIFY_REPLBATT 7 /* UPS battery needs to be replaced */
#define NOTIFY_NOCOMM 8 /* UPS hasn't been contacted in awhile */
#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 */
/* notify flag values */
@ -86,7 +92,10 @@ typedef struct {
/* flags are set to NOTIFY_SYSLOG | NOTIFY_WALL at program init */
/* the user can override with NOTIFYFLAGS in the upsmon.conf */
struct {
/* This is only used in upsmon.c, but might it also have external consumers?..
* To move or not to move?..
*/
static struct {
int type;
const char *name;
char *msg; /* NULL until overridden */
@ -104,6 +113,7 @@ struct {
{ NOTIFY_REPLBATT, "REPLBATT", NULL, "UPS %s battery needs to be replaced", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_NOCOMM, "NOCOMM", NULL, "UPS %s is unavailable", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_NOPARENT, "NOPARENT", NULL, "upsmon parent process died - shutdown impossible", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_CAL, "CAL", NULL, "UPS %s: calibration in progress", NOTIFY_SYSLOG },
{ 0, NULL, NULL, NULL, 0 }
};
@ -122,3 +132,5 @@ struct {
}
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSMON_H_SEEN */

View file

@ -1,6 +1,8 @@
/* upsrw - simple client for read/write variable access (formerly upsct2)
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
Copyright (C)
1999 Russell Kroll <rkroll@exploits.org>
2019 EATON (author: Arnaud Quette <ArnaudQuette@eaton.com>)
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,10 +27,14 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
#include "extstate.h"
static char *upsname = NULL, *hostname = NULL;
static UPSCONN_t *ups = NULL;
static int tracking_enabled = 0;
static unsigned int timeout = DEFAULT_TRACKING_TIMEOUT;
struct list_t {
char *name;
@ -39,18 +45,22 @@ static void usage(const char *prog)
{
printf("Network UPS Tools %s %s\n\n", prog, UPS_VERSION);
printf("usage: %s [-h]\n", prog);
printf(" %s [-s <variable>] [-u <username>] [-p <password>] <ups>\n\n", prog);
printf(" %s [-s <variable>] [-u <username>] [-p <password>] [-w] [-t <timeout>] <ups>\n\n", prog);
printf("Demo program to set variables within UPS hardware.\n");
printf("\n");
printf(" -h display this help text\n");
printf(" -s <variable> 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");
printf(" -u <username> set username for command authentication\n");
printf(" -p <password> set password for command authentication\n");
printf(" -w wait for the completion of setting by the driver\n");
printf(" and return its actual result from the device\n");
printf(" -t <timeout> set a timeout when using -w (in seconds, default: %u)\n", DEFAULT_TRACKING_TIMEOUT);
printf("\n");
printf(" <ups> UPS identifier - <upsname>[@<hostname>[:<port>]]\n");
printf("\n");
printf("Call without -s to show all possible read/write variables.\n");
printf("Call without -s to show all possible read/write variables (same as -l).\n");
}
static void clean_exit(void)
@ -64,9 +74,21 @@ static void clean_exit(void)
free(ups);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
static void do_set(const char *varname, const char *newval)
{
int cmd_complete = 0;
char buf[SMALLBUF], enc[SMALLBUF];
char tracking_id[UUID4_LEN];
time_t start, now;
snprintf(buf, sizeof(buf), "SET VAR %s %s \"%s\"\n", upsname, varname, pconf_encode(newval, enc, sizeof(enc)));
@ -78,17 +100,92 @@ static void do_set(const char *varname, const char *newval)
fatalx(EXIT_FAILURE, "Set variable failed: %s", upscli_strerror(ups));
}
/* FUTURE: status cookies will tie in here */
/* verify answer */
if (strncmp(buf, "OK", 2) != 0) {
fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf);
}
/* check for status tracking id */
if (
!tracking_enabled ||
/* sanity check on the size: "OK TRACKING " + UUID4_LEN */
strlen(buf) != (UUID4_LEN - 1 + strlen("OK TRACKING "))
) {
/* reply as usual */
fprintf(stderr, "%s\n", buf);
return;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic ignored "-Wformat-truncation"
#endif
/* From the check above, we know that we have exactly UUID4_LEN chars
* (aka sizeof(tracking_id)) in the buf after "OK TRACKING " prefix,
* plus the null-byte.
*/
assert (UUID4_LEN == 1 + snprintf(tracking_id, sizeof(tracking_id), "%s", buf + strlen("OK TRACKING ")));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic pop
#endif
time(&start);
/* send status tracking request, looping if status is PENDING */
while (!cmd_complete) {
/* check for timeout */
time(&now);
if (difftime(now, start) >= timeout)
fatalx(EXIT_FAILURE, "Can't receive status tracking information: timeout");
snprintf(buf, sizeof(buf), "GET TRACKING %s\n", tracking_id);
if (upscli_sendline(ups, buf, strlen(buf)) < 0)
fatalx(EXIT_FAILURE, "Can't send status tracking request: %s", upscli_strerror(ups));
#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) )
/* Note for gating macros above: unsuffixed HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP
* means support of contexts both inside and outside function body, so the push
* above and pop below (outside this finction) are not used.
*/
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
/* Note that the individual warning pragmas for use inside function bodies
* are named without a _INSIDEFUNC suffix, for simplicity and legacy reasons
*/
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* and get status tracking reply */
assert(timeout < LONG_MAX);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic pop
#endif
if (upscli_readline_timeout(ups, buf, sizeof(buf), (long)timeout) < 0)
fatalx(EXIT_FAILURE, "Can't receive status tracking information: %s", upscli_strerror(ups));
if (strncmp(buf, "PENDING", 7))
cmd_complete = 1;
else
/* wait a second before retrying */
sleep(1);
}
fprintf(stderr, "%s\n", buf);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
static void do_setvar(const char *varname, char *uin, const char *pass)
{
char newval[SMALLBUF], temp[SMALLBUF], user[SMALLBUF], *ptr;
char newval[SMALLBUF], temp[SMALLBUF * 2], user[SMALLBUF], *ptr;
struct passwd *pw;
if (uin) {
@ -177,13 +274,32 @@ static void do_setvar(const char *varname, char *uin, const char *pass)
fatalx(EXIT_FAILURE, "Error: old variable names are not supported");
}
/* enable status tracking ID */
if (tracking_enabled) {
snprintf(temp, sizeof(temp), "SET TRACKING ON\n");
if (upscli_sendline(ups, temp, strlen(temp)) < 0) {
fatalx(EXIT_FAILURE, "Can't enable set variable status tracking: %s", upscli_strerror(ups));
}
if (upscli_readline(ups, temp, sizeof(temp)) < 0) {
fatalx(EXIT_FAILURE, "Enabling set variable status tracking failed: %s", upscli_strerror(ups));
}
/* Verify the result */
if (strncmp(temp, "OK", 2) != 0) {
fatalx(EXIT_FAILURE, "Enabling set variable status tracking failed. upsd answered: %s", temp);
}
}
do_set(varname, newval);
}
static const char *get_data(const char *type, const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4];
@ -203,7 +319,7 @@ static const char *get_data(const char *type, const char *varname)
return answer[3];
}
static void do_string(const char *varname, const int len)
static void do_string(const char *varname, const long len)
{
const char *val;
@ -214,14 +330,34 @@ static void do_string(const char *varname, const int len)
}
printf("Type: STRING\n");
printf("Maximum length: %d\n", len);
printf("Maximum length: %ld\n", len);
printf("Value: %s\n", val);
}
static void do_enum(const char *varname)
static void do_number(const char *varname)
{
const char *val;
val = get_data("VAR", varname);
if (!val) {
fatalx(EXIT_FAILURE, "do_number: can't get current value of %s", varname);
}
printf("Type: NUMBER\n");
printf("Value: %s\n", val);
}
/**
* Display ENUM information
* @param varname the name of the NUT variable
* @param vartype the type of the NUT variable (ST_FLAG_STRING, ST_FLAG_NUMBER
* @param len the length of the NUT variable, if type == ST_FLAG_STRING
*/
static void do_enum(const char *varname, const int vartype, const long len)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer, buf[SMALLBUF];
const char *query[4], *val;
@ -247,14 +383,21 @@ static void do_enum(const char *varname)
ret = upscli_list_next(ups, numq, query, &numa, &answer);
/* Fallback for older upsd versions */
if (vartype != ST_FLAG_NONE)
printf("Type: ENUM %s\n", (vartype == ST_FLAG_STRING)?"STRING":"NUMBER");
else
printf("Type: ENUM\n");
if (vartype == ST_FLAG_STRING)
printf("Maximum length: %ld\n", len);
while (ret == 1) {
/* ENUM <upsname> <varname> <value> */
if (numa < 4) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
printf("Option: \"%s\"", answer[3]);
@ -272,7 +415,7 @@ static void do_enum(const char *varname)
static void do_range(const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4], *val;
int ival, min, max;
@ -299,14 +442,15 @@ static void do_range(const char *varname)
ret = upscli_list_next(ups, numq, query, &numa, &answer);
printf("Type: RANGE\n");
/* Ranges implies a type "NUMBER" */
printf("Type: RANGE NUMBER\n");
while (ret == 1) {
/* RANGE <upsname> <varname> <min> <max> */
if (numa < 5) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
min = atoi(answer[3]);
@ -327,7 +471,8 @@ static void do_range(const char *varname)
static void do_type(const char *varname)
{
int ret;
unsigned int i, numq, numa;
int is_enum = 0; /* 1 if ENUM; FIXME: add a boolean type in common.h */
size_t i, numq, numa;
char **answer;
const char *query[4];
@ -346,9 +491,11 @@ static void do_type(const char *varname)
/* TYPE <upsname> <varname> <type>... */
for (i = 3; i < numa; i++) {
/* ENUM can be NUMBER or STRING
* just flag it for latter processing */
if (!strcasecmp(answer[i], "ENUM")) {
do_enum(varname);
return;
is_enum = 1;
continue;
}
if (!strcasecmp(answer[i], "RANGE")) {
@ -359,15 +506,21 @@ static void do_type(const char *varname)
if (!strncasecmp(answer[i], "STRING:", 7)) {
char *len = answer[i] + 7;
int length = strtol(len, NULL, 10);
long length = strtol(len, NULL, 10);
if (is_enum == 1)
do_enum(varname, ST_FLAG_STRING, length);
else
do_string(varname, length);
return;
}
if (!strcasecmp(answer[i], "NUMBER")) {
printf("Type: NUMBER\n");
if (is_enum == 1)
do_enum(varname, ST_FLAG_NUMBER, 0);
else
do_number(varname);
return;
}
@ -378,6 +531,10 @@ static void do_type(const char *varname)
printf("Type: %s (unrecognized)\n", answer[i]);
}
/* Fallback for older upsd versions, where STRING|NUMBER is not
* appended to ENUM */
if (is_enum == 1)
do_enum(varname, ST_FLAG_NONE, 0);
}
static void print_rw(const char *varname)
@ -402,7 +559,7 @@ static void print_rw(const char *varname)
static void print_rwlist(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[2];
char **answer;
struct list_t *lhead, *llast, *ltmp, *lnext;
@ -436,7 +593,7 @@ static void print_rwlist(void)
/* RW <upsname> <varname> <value> */
if (numa < 4) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
/* sock this entry away for later */
@ -473,22 +630,36 @@ static void print_rwlist(void)
int main(int argc, char **argv)
{
int i, port;
int i;
uint16_t port;
const char *prog = xbasename(argv[0]);
char *password = NULL, *username = NULL, *setvar = NULL;
while ((i = getopt(argc, argv, "+hs:p:u:V")) != -1) {
while ((i = getopt(argc, argv, "+hls:p:t:u:wV")) != -1) {
switch (i)
{
case 's':
setvar = optarg;
break;
case 'l':
if (setvar) {
upslogx(LOG_WARNING, "Listing mode requested, overriding setvar specified earlier!");
setvar = NULL;
}
break;
case 'p':
password = optarg;
break;
case 't':
if (!str_to_uint(optarg, &timeout, 10))
fatal_with_errno(EXIT_FAILURE, "Could not convert the provided value for timeout ('-t' option) to unsigned int");
break;
case 'u':
username = optarg;
break;
case 'w':
tracking_enabled = 1;
break;
case 'V':
printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);
exit(EXIT_SUCCESS);

View file

@ -11,8 +11,19 @@
# from your AT lines.
case $1 in
onbattwarn)
# Send a notification mail
echo "The UPS has been on battery for awhile" \
| mail -s"UPS monitor" bofh@pager.example.com
# Create a flag-file on the filesystem, for your own processing
/usr/bin/touch /some/path/ups-on-battery
;;
ups-back-on-power)
# Delete the flag-file on the filesystem
/bin/rm -f /some/path/ups-on-battery
;;
upsgone)
logger -t upssched-cmd "The UPS has been gone for awhile"
logger -t upssched-cmd "The communication with UPS has been gone for awhile"
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"

View file

@ -46,9 +46,12 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include "upssched.h"
#include "timehead.h"
#include "nut_stdint.h"
typedef struct ttype_s {
char *name;
@ -56,14 +59,13 @@ typedef struct ttype_s {
struct ttype_s *next;
} ttype_t;
ttype_t *thead = NULL;
static conn_t *connhead = NULL;
char *cmdscript = NULL, *pipefn = NULL, *lockfn = NULL;
int verbose = 0; /* use for debugging */
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 */
const char *upsname, *notify_type;
/* ups name and notify type (string) as received from upsmon */
static const char *upsname, *notify_type;
#define PARENT_STARTED -2
#define PARENT_UNNECESSARY -3
@ -179,7 +181,7 @@ static void checktimers(void)
static void start_timer(const char *name, const char *ofsstr)
{
time_t now;
int ofs;
long ofs;
ttype_t *tmp, *last;
/* get the time */
@ -194,7 +196,7 @@ static void start_timer(const char *name, const char *ofsstr)
}
if (verbose)
upslogx(LOG_INFO, "New timer: %s (%d seconds)", name, ofs);
upslogx(LOG_INFO, "New timer: %s (%ld seconds)", name, ofs);
/* now add to the queue */
tmp = last = thead;
@ -240,7 +242,7 @@ static void cancel_timer(const char *name, const char *cname)
static void us_serialize(int op)
{
static int pipefd[2];
int ret;
ssize_t ret;
char ch;
switch(op) {
@ -270,6 +272,7 @@ static int open_sock(void)
int ret, fd;
struct sockaddr_un ssaddr;
check_unix_socket_filename(pipefn);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
@ -297,6 +300,9 @@ static int open_sock(void)
if (ret < 0)
fatal_with_errno(EXIT_FAILURE, "listen(%d, %d) failed", fd, US_LISTEN_BACKLOG);
/* don't leak socket to CMDSCRIPT */
fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
@ -329,17 +335,40 @@ static void conn_del(conn_t *target)
static int send_to_one(conn_t *conn, const char *fmt, ...)
{
int ret;
ssize_t ret;
size_t buflen;
va_list ap;
char buf[US_SOCK_BUF_LEN];
va_start(ap, 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
vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
ret = write(conn->fd, buf, strlen(buf));
buflen = strlen(buf);
if (buflen >= SSIZE_MAX) {
/* Can't compare buflen to ret */
upsdebugx(2, "send_to_one(): buffered message too large");
if ((ret < 1) || (ret != (int) strlen(buf))) {
close(conn->fd);
conn_del(conn);
return 0; /* failed */
}
ret = write(conn->fd, buf, buflen);
if ((ret < 1) || (ret != (ssize_t) buflen)) {
upsdebugx(2, "write to fd %d failed", conn->fd);
close(conn->fd);
@ -370,6 +399,9 @@ static void conn_add(int sockfd)
return;
}
/* don't leak connection to CMDSCRIPT */
fcntl(acc, F_SETFD, FD_CLOEXEC);
/* enable nonblocking I/O */
ret = fcntl(acc, F_GETFL, 0);
@ -440,19 +472,20 @@ static int sock_arg(conn_t *conn)
return 0;
}
static void log_unknown(int numarg, char **arg)
static void log_unknown(size_t numarg, char **arg)
{
int i;
size_t i;
upslogx(LOG_INFO, "Unknown command on socket: ");
for (i = 0; i < numarg; i++)
upslogx(LOG_INFO, "arg %d: %s", i, arg[i]);
upslogx(LOG_INFO, "arg %zu: %s", i, arg[i]);
}
static int sock_read(conn_t *conn)
{
int i, ret;
int i;
ssize_t ret;
char ch;
for (i = 0; i < US_MAX_READ; i++) {
@ -465,6 +498,12 @@ static int sock_read(conn_t *conn)
if ((ret == -1) && (errno == EAGAIN))
return 0;
/* O_NDELAY with zero bytes means nothing to read but
* since read() follows a succesful select() with
* ready file descriptor, ret shouldn't be 0. */
if (ret == 0)
continue;
/* some other problem */
return -1; /* error */
}
@ -594,6 +633,8 @@ static int try_connect(void)
int pipefd, ret;
struct sockaddr_un saddr;
check_unix_socket_filename(pipefn);
memset(&saddr, '\0', sizeof(saddr));
saddr.sun_family = AF_UNIX;
snprintf(saddr.sun_path, sizeof(saddr.sun_path), "%s", pipefn);
@ -659,28 +700,15 @@ static int check_parent(const char *cmd, const char *arg2)
exit(EXIT_FAILURE);
}
static void read_timeout(int sig)
{
/* ignore this */
return;
}
static void setup_sigalrm(void)
{
struct sigaction sa;
sigset_t nut_upssched_sigmask;
sigemptyset(&nut_upssched_sigmask);
sa.sa_mask = nut_upssched_sigmask;
sa.sa_flags = 0;
sa.sa_handler = read_timeout;
sigaction(SIGALRM, &sa, NULL);
}
static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
{
int i, pipefd, ret;
char buf[SMALLBUF], enc[SMALLBUF];
int i, pipefd;
ssize_t ret;
size_t enclen, buflen;
char buf[SMALLBUF], enc[SMALLBUF + 8];
int ret_s;
struct timeval tv;
fd_set fdread;
/* insanity */
if (!arg1)
@ -696,6 +724,14 @@ static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
snprintf(enc, sizeof(enc), "%s\n", buf);
/* Sanity checks, for static analyzers to sleep well */
enclen = strlen(enc);
buflen = strlen(buf);
if (enclen >= SSIZE_MAX || buflen >= SSIZE_MAX) {
/* Can't compare enclen to ret below */
fatalx(EXIT_FAILURE, "Unable to connect to daemon: buffered message too large");
}
/* see if the parent needs to be started (and maybe start it) */
for (i = 0; i < MAX_TRIES; i++) {
@ -703,7 +739,6 @@ static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
pipefd = check_parent(cmd, arg2);
if (pipefd == PARENT_STARTED) {
/* loop back and try to connect now */
usleep(250000);
continue;
@ -715,23 +750,41 @@ static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
/* we're connected now */
ret = write(pipefd, enc, strlen(enc));
ret = write(pipefd, enc, enclen);
/* if we can't send the whole thing, loop back and try again */
if ((ret < 1) || (ret != (int) strlen(enc))) {
if ((ret < 1) || (ret != (ssize_t)enclen)) {
upslogx(LOG_ERR, "write failed, trying again");
close(pipefd);
continue;
}
/* ugh - probably should use select here... */
setup_sigalrm();
/* select on child's pipe fd */
do {
/* set timeout every time before call select() */
tv.tv_sec = 1;
tv.tv_usec = 0;
alarm(2);
FD_ZERO(&fdread);
FD_SET(pipefd, &fdread);
ret_s = select(pipefd + 1, &fdread, NULL, NULL, &tv);
switch(ret_s) {
/* select error */
case -1:
upslogx(LOG_DEBUG, "parent select error: %s", strerror(errno));
break;
/* nothing to read */
case 0:
break;
/* available data to read */
default:
ret = read(pipefd, buf, sizeof(buf));
alarm(0);
signal(SIGALRM, SIG_IGN);
break;
}
} while (ret_s <= 0);
close(pipefd);
@ -747,7 +800,7 @@ static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
upslogx(LOG_ERR, "read confirmation got [%s]", buf);
/* try again ... */
}
} /* loop until MAX_TRIES if no success above */
fatalx(EXIT_FAILURE, "Unable to connect to daemon and unable to start daemon");
}
@ -794,7 +847,7 @@ static void parse_at(const char *ntype, const char *un, const char *cmd,
}
if (!strcmp(cmd, "EXECUTE")) {
if (ca1 == '\0') {
if (ca1[0] == '\0') {
upslogx(LOG_ERR, "Empty EXECUTE command argument");
return;
}
@ -809,7 +862,7 @@ static void parse_at(const char *ntype, const char *un, const char *cmd,
upslogx(LOG_ERR, "Invalid command: %s", cmd);
}
static int conf_arg(int numargs, char **arg)
static int conf_arg(size_t numargs, char **arg)
{
if (numargs < 2)
return 0;
@ -900,9 +953,15 @@ static void checkconf(void)
int main(int argc, char **argv)
{
const char *prog = xbasename(argv[0]);
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");
}
verbose = 1; /* TODO: remove when done testing */
verbose = 1; /* TODO: remove when done testing, or add -D */
/* normally we don't have stderr, so get this going to syslog early */
open_syslog(prog);

View file

@ -1,5 +1,8 @@
/* upssched.h - supporting structures */
#ifndef NUT_UPSSCHED_H_SEEN
#define NUT_UPSSCHED_H_SEEN 1
#include <parseconf.h>
#define SERIALIZE_INIT 1
@ -25,3 +28,4 @@ typedef struct conn_s {
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSSCHED_H_SEEN */

View file

@ -24,6 +24,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
#include "cgilib.h"
#include "parseconf.h"
@ -39,12 +40,12 @@ struct list_t {
#define HARD_UPSVAR_LIMIT_NUM 64
#define HARD_UPSVAR_LIMIT_LEN 256
char *monups, *username, *password, *function, *upscommand;
static char *monups, *username, *password, *function, *upscommand;
/* set once the MAGIC_ENABLE_STRING is found in the upsset.conf */
int magic_string_set = 0;
/* set once the MAGIC_ENABLE_STRING is found in the upsset.conf */
static int magic_string_set = 0;
static int port;
static uint16_t port;
static char *upsname, *hostname;
static UPSCONN_t ups;
@ -54,7 +55,7 @@ typedef struct {
void *next;
} uvtype_t;
uvtype_t *firstuv = NULL;
static uvtype_t *firstuv = NULL;
void parsearg(char *var, char *value)
{
@ -163,7 +164,7 @@ static void do_hidden(const char *next)
}
/* generate SELECT chooser from hosts.conf entries */
static void upslist_arg(int numargs, char **arg)
static void upslist_arg(size_t numargs, char **arg)
{
if (numargs < 3)
return;
@ -253,6 +254,10 @@ static void do_pickups(const char *currfunc)
printf("</FORM>\n");
}
static void error_page(const char *next, const char *title,
const char *fmt, ...)
__attribute__((noreturn));
static void error_page(const char *next, const char *title,
const char *fmt, ...)
{
@ -260,7 +265,19 @@ static void error_page(const char *next, const char *title,
va_list ap;
va_start(ap, 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
vsnprintf(msg, sizeof(msg), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
do_header(title);
@ -282,6 +299,9 @@ static void error_page(const char *next, const char *title,
exit(EXIT_SUCCESS);
}
static void loginscreen(void)
__attribute__((noreturn));
static void loginscreen(void)
{
do_header("Login");
@ -331,7 +351,7 @@ static void upsd_connect(void)
static void print_cmd(const char *cmd)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4];
@ -354,7 +374,7 @@ static void print_cmd(const char *cmd)
static void showcmds(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[2];
char **answer;
struct list_t *lhead, *llast, *ltmp, *lnext;
@ -391,7 +411,7 @@ static void showcmds(void)
/* CMD upsname cmdname */
if (numa < 3) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 3)\n", numa);
"(got %zu args, need at least 3)\n", numa);
return;
}
@ -506,6 +526,9 @@ static void send_auth(const char *next)
"Password set failed: %s", upscli_strerror(&ups));
}
static void docmd(void)
__attribute__((noreturn));
static void docmd(void)
{
char buf[SMALLBUF], *desc;
@ -595,7 +618,7 @@ static void docmd(void)
static const char *get_data(const char *type, const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4];
@ -633,7 +656,7 @@ static void do_string(const char *varname, int maxlen)
static void do_enum(const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer, *val;
const char *query[4], *tmp;
@ -661,6 +684,7 @@ static void do_enum(const char *varname)
printf("Unavailable\n");
fprintf(stderr, "Error doing ENUM %s %s: %s\n",
upsname, varname, upscli_strerror(&ups));
free(val);
return;
}
@ -674,7 +698,7 @@ static void do_enum(const char *varname)
if (numa < 4) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 4)\n", numa);
"(got %zu args, need at least 4)\n", numa);
free(val);
return;
@ -697,7 +721,7 @@ static void do_enum(const char *varname)
static void do_type(const char *varname)
{
int ret;
unsigned int i, numq, numa;
size_t i, numq, numa;
char **answer;
const char *query[4];
@ -727,7 +751,9 @@ static void do_type(const char *varname)
/* split out the :<len> data */
ptr = strchr(answer[i], ':');
*ptr++ = '\0';
len = strtol(ptr, (char **) NULL, 10);
long 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;
do_string(varname, len);
return;
@ -741,10 +767,12 @@ static void do_type(const char *varname)
}
}
static void print_rw(const char *upsname, const char *varname)
static void print_rw(const char *arg_upsname, const char *varname)
{
const char *tmp;
printf("<!-- <TR><TD>Device</TD><TD>%s</TD></TR> -->\n", arg_upsname);
printf("<TR BGCOLOR=\"#60B0B0\" ALIGN=\"CENTER\">\n");
printf("<TD>");
@ -765,10 +793,13 @@ static void print_rw(const char *upsname, const char *varname)
printf("</TR>\n");
}
static void showsettings(void)
__attribute__((noreturn));
static void showsettings(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[2];
char **answer, *desc = NULL;
struct list_t *lhead, *llast, *ltmp, *lnext;
@ -907,6 +938,9 @@ static int setvar(const char *var, const char *val)
}
/* turn a form submission of settings into SET commands for upsd */
static void savesettings(void)
__attribute__((noreturn));
static void savesettings(void)
{
int changed = 0;
@ -953,6 +987,9 @@ static void savesettings(void)
exit(EXIT_SUCCESS);
}
static void initial_pickups(void)
__attribute__((noreturn));
static void initial_pickups(void)
{
do_header("Select a UPS");
@ -1031,6 +1068,8 @@ static void check_conf(void)
int main(int argc, char **argv)
{
NUT_UNUSED_VARIABLE(argc);
NUT_UNUSED_VARIABLE(argv);
username = password = function = monups = NULL;
printf("Content-type: text/html\n\n");
@ -1047,6 +1086,7 @@ int main(int argc, char **argv)
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = 0;
tv.tv_usec = 250000; /* wait for up to 250ms for a POST response */
if ((select(STDIN_FILENO+1, &fds, 0, 0, &tv)) > 0)
extractpostargs();
}

View file

@ -19,11 +19,12 @@
*/
#include "common.h"
#include "nut_stdint.h"
#include "timehead.h"
#include "upsclient.h"
#include "status.h"
#include "cgilib.h"
#include "parseconf.h"
#include "timehead.h"
#include "upsstats.h"
#include "upsimagearg.h"
@ -36,7 +37,7 @@ static int use_celsius = 1, refreshdelay = -1, treemode = 0;
/* from cgilib's checkhost() */
static char *monhostdesc = NULL;
static int port;
static uint16_t port;
static char *upsname, *hostname;
static char *upsimgpath="upsimage.cgi", *upsstatpath="upsstats.cgi";
static UPSCONN_t ups;
@ -103,7 +104,7 @@ static int check_ups_fd(int do_report)
static int get_var(const char *var, char *buf, size_t buflen, int verbose)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -195,9 +196,10 @@ static int do_date(const char *buf)
{
char datebuf[SMALLBUF];
time_t tod;
struct tm tmbuf;
time(&tod);
if (strftime(datebuf, sizeof(datebuf), buf, localtime(&tod))) {
if (strftime(datebuf, sizeof(datebuf), buf, localtime_r(&tod, &tmbuf))) {
printf("%s", datebuf);
return 1;
}
@ -349,7 +351,7 @@ static void ups_connect(void)
{
static ulist_t *lastups = NULL;
char *newups, *newhost;
int newport;
uint16_t newport;
/* try to minimize reconnects */
if (lastups) {
@ -564,7 +566,7 @@ static void do_upsimgpath(const char *s) {
static void do_temp(const char *var)
{
char tempc[SMALLBUF];
float tempf;
double tempf;
if (!get_var(var, tempc, sizeof(tempc), 1))
return;
@ -807,7 +809,8 @@ static int do_command(char *cmd)
static void parse_line(const char *buf)
{
char cmd[SMALLBUF];
int i, len, do_cmd = 0;
size_t i, len;
char do_cmd = 0;
for (i = 0; buf[i]; i += len) {
@ -824,9 +827,10 @@ static void parse_line(const char *buf)
i++; /* skip over the '@' character */
continue;
}
assert (len < INT_MAX);
if (do_cmd) {
snprintf(cmd, sizeof(cmd), "%.*s", len, &buf[i]);
snprintf(cmd, sizeof(cmd), "%.*s", (int)len, &buf[i]);
continue;
}
@ -836,7 +840,7 @@ static void parse_line(const char *buf)
}
/* pass it trough */
printf("%.*s", len, &buf[i]);
printf("%.*s", (int)len, &buf[i]);
}
}
@ -865,7 +869,7 @@ static void display_template(const char *tfn)
static void display_tree(int verbose)
{
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -1041,6 +1045,9 @@ static void display_single(void)
int main(int argc, char **argv)
{
NUT_UNUSED_VARIABLE(argc);
NUT_UNUSED_VARIABLE(argv);
extractcgiargs();
printf("Content-type: text/html\n");

View file

@ -17,6 +17,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_UPSSTATS_H_SEEN
#define NUT_UPSSTATS_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
@ -35,3 +38,4 @@ typedef struct {
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSSTATS_H_SEEN */

View file

@ -8,10 +8,42 @@ libparseconf_la_SOURCES = parseconf.c
# do not hard depend on '../include/nut_version.h', since it blocks
# 'dist', and is only required for actual build, in which case
# BUILT_SOURCES (in ../include) will ensure nut_version.h will
# be built before anything else
libcommon_la_SOURCES = common.c state.c str.c upsconf.c
libcommonclient_la_SOURCES = common.c state.c str.c
# be built before anything else... but do depend on its build area:
if BUILDING_IN_TREE
# No need for symlink hack
common.c: $(top_builddir)/include/nut_version.h
else
# Surprisingly, for some "make" implementations this dependency means
# that the "common.c" required for builds below will be seeked in the
# current directory. So for out-of-tree builds like distcheck, we have
# to symlink the "real" source to build area:
common.c: $(top_builddir)/include/nut_version.h $(srcdir)/common.c
test -s "$@" || ln -s -f "$(top_srcdir)/common/common.c" "$@"
endif
$(top_builddir)/include/nut_version.h:
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
libcommon_la_SOURCES = state.c str.c upsconf.c
libcommonclient_la_SOURCES = state.c str.c
if BUILDING_IN_TREE
libcommon_la_SOURCES += common.c
libcommonclient_la_SOURCES += common.c
else
nodist_libcommon_la_SOURCES = common.c
nodist_libcommonclient_la_SOURCES = common.c
CLEANFILES = $(top_builddir)/common/common.c
BUILT_SOURCES = common.c
endif
# ensure inclusion of local implementation of missing systems functions
# using LTLIBOBJS. Refer to configure.in -> AC_REPLACE_FUNCS
# using LTLIBOBJS. Refer to configure.in/.ac -> AC_REPLACE_FUNCS
libcommon_la_LIBADD = libparseconf.la @LTLIBOBJS@
libcommonclient_la_LIBADD = libparseconf.la @LTLIBOBJS@
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

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -17,7 +17,17 @@
# Network UPS Tools: common
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -81,20 +91,27 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@BUILDING_IN_TREE_TRUE@am__append_1 = common.c
@BUILDING_IN_TREE_TRUE@am__append_2 = common.c
subdir = common
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am atexit.c \
snprintf.c setenv.c strerror.c $(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -103,26 +120,39 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libcommon_la_DEPENDENCIES = libparseconf.la @LTLIBOBJS@
am_libcommon_la_OBJECTS = common.lo state.lo str.lo upsconf.lo
libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS)
am__libcommon_la_SOURCES_DIST = state.c str.c upsconf.c common.c
@BUILDING_IN_TREE_TRUE@am__objects_1 = common.lo
am_libcommon_la_OBJECTS = state.lo str.lo upsconf.lo $(am__objects_1)
@BUILDING_IN_TREE_FALSE@nodist_libcommon_la_OBJECTS = common.lo
libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) \
$(nodist_libcommon_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libcommonclient_la_DEPENDENCIES = libparseconf.la @LTLIBOBJS@
am_libcommonclient_la_OBJECTS = common.lo state.lo str.lo
libcommonclient_la_OBJECTS = $(am_libcommonclient_la_OBJECTS)
am__libcommonclient_la_SOURCES_DIST = state.c str.c common.c
am_libcommonclient_la_OBJECTS = state.lo str.lo $(am__objects_1)
@BUILDING_IN_TREE_FALSE@nodist_libcommonclient_la_OBJECTS = common.lo
libcommonclient_la_OBJECTS = $(am_libcommonclient_la_OBJECTS) \
$(nodist_libcommonclient_la_OBJECTS)
libparseconf_la_LIBADD =
am_libparseconf_la_OBJECTS = parseconf.lo
libparseconf_la_OBJECTS = $(am_libparseconf_la_OBJECTS)
@ -140,7 +170,12 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = $(DEPDIR)/atexit.Plo $(DEPDIR)/setenv.Plo \
$(DEPDIR)/snprintf.Plo $(DEPDIR)/strerror.Plo \
./$(DEPDIR)/common.Plo ./$(DEPDIR)/parseconf.Plo \
./$(DEPDIR)/state.Plo ./$(DEPDIR)/str.Plo \
./$(DEPDIR)/upsconf.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -160,9 +195,12 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libcommon_la_SOURCES) $(libcommonclient_la_SOURCES) \
SOURCES = $(libcommon_la_SOURCES) $(nodist_libcommon_la_SOURCES) \
$(libcommonclient_la_SOURCES) \
$(nodist_libcommonclient_la_SOURCES) \
$(libparseconf_la_SOURCES)
DIST_SOURCES = $(libcommon_la_SOURCES) $(libcommonclient_la_SOURCES) \
DIST_SOURCES = $(am__libcommon_la_SOURCES_DIST) \
$(am__libcommonclient_la_SOURCES_DIST) \
$(libparseconf_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
@ -188,6 +226,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp atexit.c \
setenv.c snprintf.c strerror.c
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A2X = @A2X@
ACLOCAL = @ACLOCAL@
@ -196,6 +236,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -206,6 +247,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -219,6 +261,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -231,6 +274,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -248,6 +292,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -258,21 +304,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -292,6 +346,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -305,6 +362,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -322,6 +380,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -335,6 +394,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -360,12 +422,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -378,18 +442,20 @@ udevdir = @udevdir@
AM_CFLAGS = -I$(top_srcdir)/include
noinst_LTLIBRARIES = libparseconf.la libcommon.la libcommonclient.la
libparseconf_la_SOURCES = parseconf.c
libcommon_la_SOURCES = state.c str.c upsconf.c $(am__append_1)
libcommonclient_la_SOURCES = state.c str.c $(am__append_2)
@BUILDING_IN_TREE_FALSE@nodist_libcommon_la_SOURCES = common.c
@BUILDING_IN_TREE_FALSE@nodist_libcommonclient_la_SOURCES = common.c
@BUILDING_IN_TREE_FALSE@CLEANFILES = $(top_builddir)/common/common.c
@BUILDING_IN_TREE_FALSE@BUILT_SOURCES = common.c
# do not hard depend on '../include/nut_version.h', since it blocks
# 'dist', and is only required for actual build, in which case
# BUILT_SOURCES (in ../include) will ensure nut_version.h will
# be built before anything else
libcommon_la_SOURCES = common.c state.c str.c upsconf.c
libcommonclient_la_SOURCES = common.c state.c str.c
# ensure inclusion of local implementation of missing systems functions
# using LTLIBOBJS. Refer to configure.in -> AC_REPLACE_FUNCS
# using LTLIBOBJS. Refer to configure.in/.ac -> AC_REPLACE_FUNCS
libcommon_la_LIBADD = libparseconf.la @LTLIBOBJS@
libcommonclient_la_LIBADD = libparseconf.la @LTLIBOBJS@
all: all-am
MAINTAINERCLEANFILES = Makefile.in .dirstamp
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@ -405,14 +471,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu common/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -450,15 +515,21 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/atexit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/setenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseconf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsconf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/atexit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/setenv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseconf.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsconf.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@ -542,7 +613,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -573,11 +647,14 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
check: check-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@ -598,6 +675,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@ -606,13 +684,23 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f $(DEPDIR)/atexit.Plo
-rm -f $(DEPDIR)/setenv.Plo
-rm -f $(DEPDIR)/snprintf.Plo
-rm -f $(DEPDIR)/strerror.Plo
-rm -f ./$(DEPDIR)/common.Plo
-rm -f ./$(DEPDIR)/parseconf.Plo
-rm -f ./$(DEPDIR)/state.Plo
-rm -f ./$(DEPDIR)/str.Plo
-rm -f ./$(DEPDIR)/upsconf.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -658,7 +746,15 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f $(DEPDIR)/atexit.Plo
-rm -f $(DEPDIR)/setenv.Plo
-rm -f $(DEPDIR)/snprintf.Plo
-rm -f $(DEPDIR)/strerror.Plo
-rm -f ./$(DEPDIR)/common.Plo
-rm -f ./$(DEPDIR)/parseconf.Plo
-rm -f ./$(DEPDIR)/state.Plo
-rm -f ./$(DEPDIR)/str.Plo
-rm -f ./$(DEPDIR)/upsconf.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@ -677,22 +773,45 @@ ps-am:
uninstall-am:
.MAKE: install-am install-strip
.MAKE: all check install install-am install-exec install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-generic clean-libtool clean-noinstLTLIBRARIES \
cscopelist-am ctags ctags-am distclean distclean-compile \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# do not hard depend on '../include/nut_version.h', since it blocks
# 'dist', and is only required for actual build, in which case
# BUILT_SOURCES (in ../include) will ensure nut_version.h will
# be built before anything else... but do depend on its build area:
# No need for symlink hack
@BUILDING_IN_TREE_TRUE@common.c: $(top_builddir)/include/nut_version.h
# Surprisingly, for some "make" implementations this dependency means
# that the "common.c" required for builds below will be seeked in the
# current directory. So for out-of-tree builds like distcheck, we have
# to symlink the "real" source to build area:
@BUILDING_IN_TREE_FALSE@common.c: $(top_builddir)/include/nut_version.h $(srcdir)/common.c
@BUILDING_IN_TREE_FALSE@ test -s "$@" || ln -s -f "$(top_srcdir)/common/common.c" "$@"
$(top_builddir)/include/nut_version.h:
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
# 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
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View file

@ -1,6 +1,7 @@
/* common.c - common useful functions
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
Copyright (C) 2021-2022 Jim Klimov <jimklimov+nut@gmail.com>
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
@ -21,8 +22,11 @@
#include <ctype.h>
#include <syslog.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
#include <sys/un.h>
/* the reason we define UPS_VERSION as a static string, rather than a
macro, is to make dependency tracking easier (only common.o depends
@ -32,6 +36,52 @@
#include "nut_version.h"
const char *UPS_VERSION = NUT_VERSION_MACRO;
#include <stdio.h>
/* Know which bitness we were built for,
* to adjust the search paths for get_libname() */
#include "nut_stdint.h"
#if UINTPTR_MAX == 0xffffffffffffffffULL
# define BUILD_64 1
#else
# ifdef BUILD_64
# undef BUILD_64
# endif
#endif
/* https://stackoverflow.com/a/12844426/4715872 */
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
pid_t get_max_pid_t()
{
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
if (sizeof(pid_t) == sizeof(short)) return (pid_t)SHRT_MAX;
if (sizeof(pid_t) == sizeof(int)) return (pid_t)INT_MAX;
if (sizeof(pid_t) == sizeof(long)) return (pid_t)LONG_MAX;
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined _STDC_C99) || (defined __C99FEATURES__) /* C99+ build mode */
# if defined(LLONG_MAX) /* since C99 */
if (sizeof(pid_t) == sizeof(long long)) return (pid_t)LLONG_MAX;
# endif
#endif
abort();
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
}
int nut_debug_level = 0;
int nut_log_level = 0;
static int upslog_flags = UPSLOG_STDERR;
@ -164,7 +214,31 @@ struct passwd *get_user_pwent(const char *name)
else
fatal_with_errno(EXIT_FAILURE, "getpwnam(%s)", name);
return NULL; /* to make the compiler happy */
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) || (defined HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE_RETURN) )
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE_RETURN
#pragma GCC diagnostic ignored "-Wunreachable-code-return"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
# ifdef HAVE_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE_RETURN
# pragma clang diagnostic ignored "-Wunreachable-code-return"
# endif
#endif
/* Oh joy, adding unreachable "return" to make one compiler happy,
* and pragmas around to make other compilers happy, all at once! */
return NULL;
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) || (defined HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE_RETURN) )
#pragma GCC diagnostic pop
#endif
}
/* change to the user defined in the struct */
@ -208,7 +282,7 @@ void writepid(const char *name)
{
char fn[SMALLBUF];
FILE *pidf;
int mask;
mode_t mask;
/* use full path if present, else build filename in PIDPATH */
if (*name == '/')
@ -220,7 +294,9 @@ void writepid(const char *name)
pidf = fopen(fn, "w");
if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
intmax_t pid = (intmax_t)getpid();
upsdebugx(1, "Saving PID %jd into %s", pid, fn);
fprintf(pidf, "%jd\n", pid);
fclose(pidf);
} else {
upslog_with_errno(LOG_NOTICE, "writepid: fopen %s", fn);
@ -229,30 +305,17 @@ void writepid(const char *name)
umask(mask);
}
/* open pidfn, get the pid, then send it sig */
int sendsignalfn(const char *pidfn, int sig)
/* send sig to pid, returns -1 for error, or
* zero for a successfully sent signal
*/
int sendsignalpid(pid_t pid, int sig)
{
char buf[SMALLBUF];
FILE *pidf;
int pid, ret;
int ret;
pidf = fopen(pidfn, "r");
if (!pidf) {
upslog_with_errno(LOG_NOTICE, "fopen %s", pidfn);
return -1;
}
if (fgets(buf, sizeof(buf), pidf) == NULL) {
upslogx(LOG_NOTICE, "Failed to read pid from %s", pidfn);
fclose(pidf);
return -1;
}
pid = strtol(buf, (char **)NULL, 10);
if (pid < 2) {
upslogx(LOG_NOTICE, "Ignoring invalid pid number %d", pid);
fclose(pidf);
if (pid < 2 || pid > get_max_pid_t()) {
upslogx(LOG_NOTICE,
"Ignoring invalid pid number %" PRIdMAX,
(intmax_t) pid);
return -1;
}
@ -261,21 +324,78 @@ int sendsignalfn(const char *pidfn, int sig)
if (ret < 0) {
perror("kill");
fclose(pidf);
return -1;
}
if (sig != 0) {
/* now actually send it */
ret = kill(pid, sig);
if (ret < 0) {
perror("kill");
fclose(pidf);
return -1;
}
}
return 0;
}
/* parses string buffer into a pid_t if it passes
* a few sanity checks; returns -1 on error
*/
pid_t parsepid(const char *buf)
{
pid_t pid = -1;
/* assuming 10 digits for a long */
intmax_t _pid = strtol(buf, (char **)NULL, 10);
if (_pid <= get_max_pid_t()) {
pid = (pid_t)_pid;
} else {
upslogx(LOG_NOTICE, "Received a pid number too big for a pid_t: %" PRIdMAX, _pid);
}
return pid;
}
/* open pidfn, get the pid, then send it sig
* returns negative codes for errors, or
* zero for a successfully sent signal
*/
int sendsignalfn(const char *pidfn, int sig)
{
char buf[SMALLBUF];
FILE *pidf;
pid_t pid = -1;
int ret = -1;
pidf = fopen(pidfn, "r");
if (!pidf) {
upslog_with_errno(LOG_NOTICE, "fopen %s", pidfn);
return -3;
}
if (fgets(buf, sizeof(buf), pidf) == NULL) {
upslogx(LOG_NOTICE, "Failed to read pid from %s", pidfn);
fclose(pidf);
return -2;
}
/* TOTHINK: Original code only closed pidf before
* exiting the method, on error or "normally".
* Why not here? Do we want an (exclusive?) hold
* on it while being active in the method?
*/
/* this method actively reports errors, if any */
pid = parsepid(buf);
if (pid >= 0) {
/* this method actively reports errors, if any */
ret = sendsignalpid(pid, sig);
}
fclose(pidf);
return 0;
return ret;
}
int snprintfcat(char *dst, size_t size, const char *fmt, ...)
@ -285,14 +405,46 @@ int snprintfcat(char *dst, size_t size, const char *fmt, ...)
int ret;
size--;
assert(len <= size);
if (len > size) {
/* Do not truncate existing string */
errno = ERANGE;
return -1;
}
va_start(ap, 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
/* Note: this code intentionally uses a caller-provided format string */
ret = vsnprintf(dst + len, size - len, fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
dst[size] = '\0';
return len + ret;
/* Note: there is a standards loophole here: strlen() must return size_t
* and printf() family returns a signed int with negatives for errors.
* In theory it can overflow a 64-vs-32 bit range, or signed-vs-unsigned.
* In practice we hope to not have gigabytes-long config strings.
*/
if (ret < 0) {
return ret;
}
#ifdef INT_MAX
if ( ( (unsigned long long)len + (unsigned long long)ret ) >= (unsigned long long)INT_MAX ) {
errno = ERANGE;
return -1;
}
#endif
return (int)len + ret;
}
/* lazy way to send a signal if the program uses the PIDPATH */
@ -319,7 +471,27 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror)
int ret;
char buf[LARGEBUF];
#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
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#pragma clang diagnostic ignored "-Wformat-security"
#endif
ret = vsnprintf(buf, sizeof(buf), fmt, va);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
if ((ret < 0) || (ret >= (int) sizeof(buf)))
syslog(LOG_WARNING, "vupslog: vsnprintf needed more than %d bytes",
@ -329,7 +501,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror)
snprintfcat(buf, sizeof(buf), ": %s", strerror(errno));
if (nut_debug_level > 0) {
static struct timeval start = { 0 };
static struct timeval start = { 0, 0 };
struct timeval now;
gettimeofday(&now, NULL);
@ -368,29 +540,78 @@ const char * dflt_statepath(void)
{
const char * path;
if ((path = getenv("NUT_STATEPATH")) == NULL)
path = getenv("NUT_STATEPATH");
if ( (path == NULL) || (*path == '\0') )
path = STATEPATH;
return path;
}
/* Return the alternate path for pid files */
/* Return the alternate path for pid files, for processes running as non-root
* Per documentation and configure script, the fallback value is the
* state-file path as the daemon and drivers can write there too.
* Note that this differs from PIDPATH that higher-privileged daemons, such
* as upsmon, tend to use.
*/
const char * altpidpath(void)
{
const char * path;
path = getenv("NUT_ALTPIDPATH");
if ( (path == NULL) || (*path == '\0') )
path = getenv("NUT_STATEPATH");
if ( (path != NULL) && (*path != '\0') )
return path;
#ifdef ALTPIDPATH
return ALTPIDPATH;
#else
return dflt_statepath();
/* We assume, here and elsewhere, that at least STATEPATH is always defined */
return STATEPATH;
#endif
}
/* Die with a standard message if socket filename is too long */
void check_unix_socket_filename(const char *fn) {
struct sockaddr_un ssaddr;
if (strlen(fn) < sizeof(ssaddr.sun_path))
return;
/* Avoid useless truncated pathnames that
* other driver instances would conflict
* with, and upsd can not discover.
* Note this is quite short on many OSes
* varying 104-108 bytes (UNIX_PATH_MAX)
* as opposed to PATH_MAX or MAXPATHLEN
* typically of a kilobyte range.
*/
fatalx(EXIT_FAILURE,
"Can't create a unix domain socket: pathname '%s' "
"is too long (%zu) for 'struct sockaddr_un->sun_path' "
"on this system (%zu)",
fn, strlen(fn), sizeof(ssaddr.sun_path));
}
/* logs the formatted string to any configured logging devices + the output of strerror(errno) */
void upslog_with_errno(int priority, const char *fmt, ...)
{
va_list va;
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
vupslog(priority, fmt, va, 1);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
}
@ -400,44 +621,115 @@ void upslogx(int priority, const char *fmt, ...)
va_list va;
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
vupslog(priority, fmt, va, 0);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
}
void upsdebug_with_errno(int level, const char *fmt, ...)
void s_upsdebug_with_errno(int level, const char *fmt, ...)
{
va_list va;
char fmt2[LARGEBUF];
/* Note: Thanks to macro wrapping, we do not quite need this
* test now, but we still need the "level" value to report
* below - when it is not zero.
*/
if (nut_debug_level < level)
return;
/* For debugging output, we want to prepend the debug level so the user can
* e.g. lower the level (less -D's on command line) to retain just the amount
* of logging info he needs to see at the moment. Using '-DDDDD' all the time
* is too brutal and needed high-level overview can be lost. This [D#] prefix
* 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 ((ret < 0) || (ret >= (int) sizeof(fmt2))) {
syslog(LOG_WARNING, "upsdebug_with_errno: snprintf needed more than %d bytes",
LARGEBUF);
} else {
fmt = (const char *)fmt2;
}
}
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
vupslog(LOG_DEBUG, fmt, va, 1);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
}
void upsdebugx(int level, const char *fmt, ...)
void s_upsdebugx(int level, const char *fmt, ...)
{
va_list va;
char fmt2[LARGEBUF];
if (nut_debug_level < level)
return;
/* 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 ((ret < 0) || (ret >= (int) sizeof(fmt2))) {
syslog(LOG_WARNING, "upsdebugx: snprintf needed more than %d bytes",
LARGEBUF);
} else {
fmt = (const char *)fmt2;
}
}
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
vupslog(LOG_DEBUG, fmt, va, 0);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
}
/* dump message msg and len bytes from buf to upsdebugx(level) in
hexadecimal. (This function replaces Philippe Marzouk's original
dump_hex() function) */
void upsdebug_hex(int level, const char *msg, const void *buf, int len)
void s_upsdebug_hex(int level, const char *msg, const void *buf, size_t len)
{
char line[100];
int n; /* number of characters currently in line */
int i; /* number of bytes output from buffer */
size_t i; /* number of bytes output from buffer */
n = snprintf(line, sizeof(line), "%s: (%d bytes) =>", msg, len);
n = snprintf(line, sizeof(line), "%s: (%zu bytes) =>", msg, len);
if (n < 0) goto failed;
for (i = 0; i < len; i++) {
@ -447,9 +739,16 @@ void upsdebug_hex(int level, const char *msg, const void *buf, int len)
}
n = snprintfcat(line, sizeof(line), n ? " %02x" : "%02x",
((unsigned char *)buf)[i]);
((const unsigned char *)buf)[i]);
if (n < 0) goto failed;
}
upsdebugx(level, "%s", line);
s_upsdebugx(level, "%s", line);
return;
failed:
s_upsdebugx(level, "%s", "Failed to print a hex dump for debug");
}
/* taken from www.asciitable.com */
@ -489,29 +788,37 @@ static const char* ascii_symb[] = {
};
/* dump message msg and len bytes from buf to upsdebugx(level) in ascii. */
void upsdebug_ascii(int level, const char *msg, const void *buf, int len)
void s_upsdebug_ascii(int level, const char *msg, const void *buf, size_t len)
{
char line[256];
int i;
int n; /* number of characters currently in line */
size_t i; /* number of bytes output from buffer */
unsigned char ch;
if (nut_debug_level < level)
return; /* save cpu cycles */
snprintf(line, sizeof(line), "%s", msg);
n = snprintf(line, sizeof(line), "%s", msg);
if (n < 0) goto failed;
for (i=0; i<len; ++i) {
ch = ((unsigned char *)buf)[i];
ch = ((const unsigned char *)buf)[i];
if (ch < 0x20)
snprintfcat(line, sizeof(line), "%3s ", ascii_symb[ch]);
n = snprintfcat(line, sizeof(line), "%3s ", ascii_symb[ch]);
else if (ch >= 0x80)
snprintfcat(line, sizeof(line), "%02Xh ", ch);
n = snprintfcat(line, sizeof(line), "%02Xh ", ch);
else
snprintfcat(line, sizeof(line), "'%c' ", ch);
n = snprintfcat(line, sizeof(line), "'%c' ", ch);
if (n < 0) goto failed;
}
upsdebugx(level, "%s", line);
s_upsdebugx(level, "%s", line);
return;
failed:
s_upsdebugx(level, "%s", "Failed to print an ASCII data dump for debug");
}
static void vfatal(const char *fmt, va_list va, int use_strerror)
@ -521,7 +828,19 @@ static void vfatal(const char *fmt, va_list va, int use_strerror)
if (xbit_test(upslog_flags, UPSLOG_SYSLOG_ON_FATAL))
xbit_set(&upslog_flags, UPSLOG_SYSLOG);
#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
vupslog(LOG_ERR, fmt, va, use_strerror);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
void fatal_with_errno(int status, const char *fmt, ...)
@ -529,7 +848,19 @@ void fatal_with_errno(int status, const char *fmt, ...)
va_list va;
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
vfatal(fmt, va, (errno > 0) ? 1 : 0);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
exit(status);
@ -540,7 +871,19 @@ void fatalx(int status, const char *fmt, ...)
va_list va;
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
vfatal(fmt, va, 0);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(va);
exit(status);
@ -587,7 +930,7 @@ char *xstrdup(const char *string)
/* Read up to buflen bytes from fd and return the number of bytes
read. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
int select_read(const int fd, void *buf, const size_t buflen, const long d_sec, const long d_usec)
ssize_t select_read(const int fd, void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
fd_set fds;
@ -611,7 +954,7 @@ int select_read(const int fd, void *buf, const size_t buflen, const long d_sec,
/* Write up to buflen bytes to fd and return the number of bytes
written. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
int select_write(const int fd, const void *buf, const size_t buflen, const long d_sec, const long d_usec)
ssize_t select_write(const int fd, const void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
fd_set fds;
@ -631,3 +974,106 @@ int select_write(const int fd, const void *buf, const size_t buflen, const long
return write(fd, buf, buflen);
}
/* FIXME: would be good to get more from /etc/ld.so.conf[.d] and/or
* LD_LIBRARY_PATH and a smarter dependency on build bitness; also
* note that different OSes can have their pathnames set up differently
* with regard to default/preferred bitness (maybe a "32" in the name
* should also be searched explicitly - again, IFF our build is 32-bit).
*
* General premise for this solution is that some parts of NUT (e.g. the
* nut-scanner tool, or DMF feature code) must be pre-built and distributed
* in binary packages, but only at run-time it gets to know which third-party
* libraries it should use for particular operations. This differs from e.g.
* distribution packages which group NUT driver binaries explicitly dynamically
* linked against certain OS-provided libraries for accessing this or that
* communications media and/or vendor protocol.
*/
static const char * search_paths[] = {
/* Use the library path (and bitness) provided during ./configure first */
LIBDIR,
"/usr"LIBDIR,
"/usr/local"LIBDIR,
#ifdef BUILD_64
/* Fall back to explicit preference of 64-bit paths as named on some OSes */
"/usr/lib/64",
"/usr/lib64",
#endif
"/usr/lib",
#ifdef BUILD_64
"/lib/64",
"/lib64",
#endif
"/lib",
#ifdef BUILD_64
"/usr/local/lib/64",
"/usr/local/lib64",
#endif
"/usr/local/lib",
#ifdef AUTOTOOLS_TARGET_SHORT_ALIAS
"/usr/lib/" AUTOTOOLS_TARGET_SHORT_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_TARGET_SHORT_ALIAS,
#else
# ifdef AUTOTOOLS_HOST_SHORT_ALIAS
"/usr/lib/" AUTOTOOLS_HOST_SHORT_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_HOST_SHORT_ALIAS,
# else
# ifdef AUTOTOOLS_BUILD_SHORT_ALIAS
"/usr/lib/" AUTOTOOLS_BUILD_SHORT_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_BUILD_SHORT_ALIAS,
# endif
# endif
#endif
#ifdef AUTOTOOLS_TARGET_ALIAS
"/usr/lib/" AUTOTOOLS_TARGET_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_TARGET_ALIAS,
#else
# ifdef AUTOTOOLS_HOST_ALIAS
"/usr/lib/" AUTOTOOLS_HOST_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_HOST_ALIAS,
# else
# ifdef AUTOTOOLS_BUILD_ALIAS
"/usr/lib/" AUTOTOOLS_BUILD_ALIAS,
"/usr/lib/gcc/" AUTOTOOLS_BUILD_ALIAS,
# endif
# endif
#endif
NULL
};
char * get_libname(const char* base_libname)
{
DIR *dp;
struct dirent *dirp;
int index = 0;
char *libname_path = NULL;
char current_test_path[LARGEBUF];
size_t base_libname_length = strlen(base_libname);
for(index = 0 ; (search_paths[index] != NULL) && (libname_path == NULL) ; index++)
{
memset(current_test_path, 0, LARGEBUF);
if ((dp = opendir(search_paths[index])) == NULL)
continue;
upsdebugx(2,"Looking for lib %s in directory #%d : %s", base_libname, index, search_paths[index]);
while ((dirp = readdir(dp)) != NULL)
{
upsdebugx(5,"Comparing lib %s with dirpath %s", base_libname, dirp->d_name);
int compres = strncmp(dirp->d_name, base_libname, base_libname_length);
if(compres == 0) {
snprintf(current_test_path, LARGEBUF, "%s/%s", search_paths[index], dirp->d_name);
libname_path = realpath(current_test_path, NULL);
upsdebugx(2,"Candidate path for lib %s is %s (realpath %s)", base_libname, current_test_path, (libname_path!=NULL)?libname_path:"NULL");
if (libname_path != NULL)
break;
}
}
closedir(dp);
}
upsdebugx(1,"Looking for lib %s, found %s", base_libname, (libname_path!=NULL)?libname_path:"NULL");
return libname_path;
}

View file

@ -76,6 +76,8 @@
*
*/
#include "common.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@ -83,8 +85,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "parseconf.h"
#include "attribute.h"
#include "nut_stdint.h"
/* possible states */
@ -97,6 +102,9 @@
#define STATE_ENDOFLINE 7
#define STATE_PARSEERR 8
static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt)
__attribute__((noreturn));
static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt)
{
if (ctx->errhandler)
@ -109,7 +117,7 @@ static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt)
static void add_arg_word(PCONF_CTX_t *ctx)
{
int argpos;
size_t argpos;
size_t wbuflen;
/* this is where the new value goes */
@ -171,7 +179,7 @@ static void addchar(PCONF_CTX_t *ctx)
wbuflen = strlen(ctx->wordbuf);
/* CVE-2012-2944: only allow the subset Ascii charset from Space to ~ */
/* CVE-2012-2944: only allow the subset of ASCII charset from Space to ~ */
if ((ctx->ch < 0x20) || (ctx->ch > 0x7f)) {
fprintf(stderr, "addchar: discarding invalid character (0x%02x)!\n",
ctx->ch);
@ -199,7 +207,7 @@ static void addchar(PCONF_CTX_t *ctx)
ctx->wordptr = &ctx->wordbuf[wbuflen];
}
*ctx->wordptr++ = ctx->ch;
*ctx->wordptr++ = (char)ctx->ch;
*ctx->wordptr = '\0';
}
@ -234,7 +242,7 @@ static int findwordstart(PCONF_CTX_t *ctx)
return STATE_FINDEOL;
/* space = not in a word yet, so loop back */
if (isspace(ctx->ch))
if (isspace((size_t)ctx->ch))
return STATE_FINDWORDSTART;
/* \ = literal = accept the next char blindly */
@ -334,7 +342,7 @@ static int collect(PCONF_CTX_t *ctx)
}
/* space means the word is done */
if (isspace(ctx->ch)) {
if (isspace((size_t)ctx->ch)) {
endofword(ctx);
return STATE_FINDWORDSTART;
@ -443,6 +451,9 @@ int pconf_file_begin(PCONF_CTX_t *ctx, const char *fn)
return 0;
}
/* prevent fd leaking to child processes */
fcntl(fileno(ctx->f), F_SETFD, FD_CLOEXEC);
return 1; /* OK */
}

View file

@ -16,6 +16,7 @@ int nut_setenv(const char *name, const char *value, int overwrite)
return 0;
}
}
buffer = xmalloc(strlen(value) + strlen(name) + 2);
strcpy(buffer, name);
strcat(buffer, "=");

View file

@ -54,7 +54,7 @@
#include "config.h"
#include <string.h>
# include <ctype.h>
#include <ctype.h>
#include <sys/types.h>
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
@ -137,10 +137,26 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
/* Conversion Flags */
#define DP_C_SHORT 1
/* Note: Originally DP_C_SHORT converted to "short int" types, but modernish
* (C99+ or even earlier) standards require that the minimal type passed
* through variadic args '...' is an int, and smaller types are padded up
* to it - so value shifts in memory and erroneous access crashes can occur
* if smaller data is accessed blindly. Code below has been fixed to not pass
* "short int" anymore - it just casts the int to desired smaller type (and
* so drops the padding bits). */
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define DP_C_LLONG 4
#ifdef C89PLUS
#undef C89PLUS
#endif
#if defined(__STDC__) || defined(__STDC_VERSION__)
/* C89+ and C90+ code respectively */
#define C89PLUS 1
#endif
#define char_to_int(p) ((p)- '0')
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
@ -275,7 +291,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (short int)va_arg (args, int);
#else
value = va_arg (args, short int);
#endif
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else if (cflags == DP_C_LLONG)
@ -287,7 +307,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
@ -299,7 +323,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
@ -310,10 +338,16 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
break;
case 'X':
flags |= DP_F_UP;
goto fallthrough_case_x;
case 'x':
fallthrough_case_x:
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
@ -332,7 +366,9 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
break;
case 'E':
flags |= DP_F_UP;
goto fallthrough_case_e;
case 'e':
fallthrough_case_e:
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
@ -340,7 +376,9 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
break;
case 'G':
flags |= DP_F_UP;
goto fallthrough_case_g;
case 'g':
fallthrough_case_g:
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
@ -543,6 +581,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
}
}
#ifndef HAVE_ABS_VAL
static LDOUBLE abs_val (LDOUBLE value)
{
LDOUBLE result = value;
@ -552,7 +591,13 @@ static LDOUBLE abs_val (LDOUBLE value)
return result;
}
#endif
#ifndef HAVE_FCVT
/* The two routines that may get defined below are only used if we also don't
* have a fcvt() in the system. Defining and not using the routines may be a
* warning (fatal with -Werror), so we hide them here. */
# ifndef HAVE_POW10
static LDOUBLE pow10 (int exp)
{
LDOUBLE result = 1;
@ -565,7 +610,9 @@ static LDOUBLE pow10 (int exp)
return result;
}
# endif
# ifndef HAVE_ROUND
static long round (LDOUBLE value)
{
long intpart;
@ -577,6 +624,8 @@ static long round (LDOUBLE value)
return intpart;
}
# endif
#endif /* HAVE_FCVT */
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
@ -602,9 +651,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
#ifndef HAVE_FCVT
int caps = 0;
long intpart;
long fracpart;
#endif
/*
* AIX manpage says the default is 0, but Solaris says the default

View file

@ -20,6 +20,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h" /* must be first */
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
@ -124,7 +126,10 @@ static void st_tree_node_add(st_tree_t **nptr, st_tree_t *sptr)
*nptr = sptr;
}
/* remove a variable from a tree */
/* remove a variable from a tree
* except for variables with ST_FLAG_IMMUTABLE
* (for override.* to survive) per issue #737
*/
int state_delinfo(st_tree_t **nptr, const char *var)
{
while (*nptr) {
@ -141,6 +146,11 @@ int state_delinfo(st_tree_t **nptr, const char *var)
continue;
}
if (node->flags & ST_FLAG_IMMUTABLE) {
upsdebugx(6, "%s: not deleting immutable variable [%s]", __func__, var);
return 0;
}
/* whatever is on the left, hang it off current right */
st_tree_node_add(&node->right, node->left);
@ -303,7 +313,7 @@ int state_addrange(st_tree_t *root, const char *var, const int min, const int ma
int state_setaux(st_tree_t *root, const char *var, const char *auxs)
{
st_tree_t *sttmp;
int aux;
long aux;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
@ -354,7 +364,7 @@ int state_getflags(st_tree_t *root, const char *var)
return sttmp->flags;
}
int state_getaux(st_tree_t *root, const char *var)
long state_getaux(st_tree_t *root, const char *var)
{
st_tree_t *sttmp;
@ -396,9 +406,9 @@ const range_t *state_getrangelist(st_tree_t *root, const char *var)
return sttmp->range_list;
}
void state_setflags(st_tree_t *root, const char *var, int numflags, char **flag)
void state_setflags(st_tree_t *root, const char *var, size_t numflags, char **flag)
{
int i;
size_t i;
st_tree_t *sttmp;
/* find the tree node for var */
@ -424,6 +434,11 @@ void state_setflags(st_tree_t *root, const char *var, int numflags, char **flag)
continue;
}
if (!strcasecmp(flag[i], "NUMBER")) {
sttmp->flags |= ST_FLAG_NUMBER;
continue;
}
upsdebugx(2, "Unrecognized flag [%s]", flag[i]);
}
}

View file

@ -20,12 +20,21 @@
*
*/
#include "config.h" /* must be first */
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRING_H
#include <string.h> /* for strdup() and many others */
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h> /* for strncasecmp() and strcasecmp() */
#endif
#include "nut_stdint.h"
#include "str.h"
char *str_trim(char *string, const char character)
@ -109,7 +118,7 @@ char *str_ltrim_space(char *string)
while (
*string != '\0' &&
isspace(*string)
isspace((size_t)*string)
)
memmove(string, string + 1, strlen(string));
@ -130,7 +139,7 @@ char *str_rtrim_space(char *string)
while (
ptr >= string &&
isspace(*ptr)
isspace((size_t)*ptr)
)
*ptr-- = '\0';
@ -252,7 +261,7 @@ int str_to_short(const char *string, short *number, const int base)
return 0;
}
*number = num;
*number = (short)num;
return 1;
}
@ -273,7 +282,7 @@ int str_to_short_strict(const char *string, short *number, const int base)
return 0;
}
*number = num;
*number = (short)num;
return 1;
}
@ -291,7 +300,7 @@ int str_to_ushort(const char *string, unsigned short *number, const int base)
return 0;
}
*number = num;
*number = (unsigned short)num;
return 1;
}
@ -309,13 +318,13 @@ int str_to_ushort_strict(const char *string, unsigned short *number, const int b
return 0;
}
*number = num;
*number = (unsigned short)num;
return 1;
}
int str_to_int(const char *string, int *number, const int base)
{
long num;
long num; /* long >= int, make sure we fit well */
*number = 0;
@ -330,13 +339,13 @@ int str_to_int(const char *string, int *number, const int base)
return 0;
}
*number = num;
*number = (int)num;
return 1;
}
int str_to_int_strict(const char *string, int *number, const int base)
{
long num;
long num; /* long >= int, make sure we fit well */
*number = 0;
@ -351,13 +360,13 @@ int str_to_int_strict(const char *string, int *number, const int base)
return 0;
}
*number = num;
*number = (int)num;
return 1;
}
int str_to_uint(const char *string, unsigned int *number, const int base)
{
unsigned long num;
unsigned long num; /* long >= int, make sure we fit well */
*number = 0;
@ -369,13 +378,13 @@ int str_to_uint(const char *string, unsigned int *number, const int base)
return 0;
}
*number = num;
*number = (unsigned int)num;
return 1;
}
int str_to_uint_strict(const char *string, unsigned int *number, const int base)
{
unsigned long num;
unsigned long num; /* long >= int, make sure we fit well */
*number = 0;
@ -387,7 +396,7 @@ int str_to_uint_strict(const char *string, unsigned int *number, const int base)
return 0;
}
*number = num;
*number = (unsigned int)num;
return 1;
}
@ -429,7 +438,7 @@ int str_to_long_strict(const char *string, long *number, const int base)
if (
string == NULL ||
*string == '\0' ||
isspace(*string)
isspace((size_t)*string)
) {
errno = EINVAL;
return 0;
@ -495,7 +504,7 @@ int str_to_ulong_strict(const char *string, unsigned long *number, const int bas
*string == '\0' ||
*string == '+' ||
*string == '-' ||
isspace(*string)
isspace((size_t)*string)
) {
errno = EINVAL;
return 0;
@ -559,7 +568,7 @@ int str_to_double_strict(const char *string, double *number, const int base)
if (
string == NULL ||
*string == '\0' ||
isspace(*string)
isspace((size_t)*string)
) {
errno = EINVAL;
return 0;
@ -605,3 +614,16 @@ int str_to_double_strict(const char *string, double *number, const int base)
return 1;
}
int str_ends_with(const char *s, const char *suff) {
size_t slen;
size_t sufflen;
if (!s) return 0; /* null string does not end with anything */
if (!suff) return 1; /* null suffix tails anything */
slen = strlen(s);
sufflen = strlen(suff);
return (slen >= sufflen) && (!memcmp(s + slen - sufflen, suff, sufflen));
}

View file

@ -11,6 +11,16 @@ char *strerror(int errnum)
{
static char buf[32];
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE_BREAK
#pragma GCC diagnostic ignored "-Wunreachable-code-break"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
switch (errnum) {
#if defined (EPERM)
case EPERM:
@ -498,6 +508,11 @@ char *strerror(int errnum)
/* Fallback: just print the error number */
snprintf(buf, sizeof(buf), "Error %d", errnum);
return buf;
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
}
#endif /* HAVE_STRERROR */

View file

@ -17,6 +17,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h" /* must be the first header */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -29,7 +31,7 @@
static char *ups_section;
/* handle arguments separated by parseconf */
static void conf_args(int numargs, char **arg)
static void conf_args(size_t numargs, char **arg)
{
if (numargs < 1)
return;

View file

@ -15,3 +15,27 @@ endif
dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL)
nodist_sysconf_DATA = upssched.conf.sample upsmon.conf.sample
SPELLCHECK_SRC = $(dist_sysconf_DATA) \
upssched.conf.sample.in upsmon.conf.sample.in
# 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)" $@
# 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)" $@
.in.in-spellchecked:
$(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@
spellcheck spellcheck-interactive spellcheck-sortdict:
$(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_DIR="$(srcdir)" $@
MAINTAINERCLEANFILES = Makefile.in .dirstamp
CLEANFILES = *.pdf *.html *-spellchecked

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -17,7 +17,17 @@
# Network UPS Tools: conf
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -82,21 +92,24 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = conf
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/upsmon.conf.sample.in \
$(srcdir)/upssched.conf.sample.in \
$(am__dist_sysconf_DATA_DIST)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -105,11 +118,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_sysconf_DATA_DIST) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = upsmon.conf.sample upssched.conf.sample
@ -167,6 +187,9 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(sysconfdir)"
DATA = $(dist_sysconf_DATA) $(nodist_sysconf_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(srcdir)/upsmon.conf.sample.in \
$(srcdir)/upssched.conf.sample.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A2X = @A2X@
ACLOCAL = @ACLOCAL@
@ -175,6 +198,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -185,6 +209,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -198,6 +223,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -210,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -227,6 +254,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -237,21 +266,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -271,6 +308,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -284,6 +324,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -301,6 +342,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -314,6 +356,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -339,12 +384,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -364,9 +411,15 @@ CGIPUB = hosts.conf.sample upsset.conf.sample upsstats.html.sample \
@WITH_CGI_TRUE@CGI_INSTALL = $(CGIPUB)
dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL)
nodist_sysconf_DATA = upssched.conf.sample upsmon.conf.sample
SPELLCHECK_SRC = $(dist_sysconf_DATA) \
upssched.conf.sample.in upsmon.conf.sample.in
MAINTAINERCLEANFILES = Makefile.in .dirstamp
CLEANFILES = *.pdf *.html *-spellchecked
all: all-am
.SUFFIXES:
.SUFFIXES: .in .in-spellchecked .sample .sample-spellchecked
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -379,14 +432,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu conf/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu conf/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -456,7 +508,10 @@ ctags CTAGS:
cscope cscopelist:
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -515,6 +570,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@ -523,6 +579,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
@ -606,6 +663,25 @@ uninstall-am: uninstall-dist_sysconfDATA uninstall-nodist_sysconfDATA
uninstall-am uninstall-dist_sysconfDATA \
uninstall-nodist_sysconfDATA
.PRECIOUS: Makefile
# 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)" $@
# 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)" $@
.in.in-spellchecked:
$(MAKE) -s -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC_ONE="$<" SPELLCHECK_DIR="$(srcdir)" $@
spellcheck spellcheck-interactive spellcheck-sortdict:
$(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_DIR="$(srcdir)" $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View file

@ -26,7 +26,14 @@
# - netclient: this mode only requires upsmon.
#
# IMPORTANT NOTE:
# This file is intended to be sourced by shell scripts.
# 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!
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:
#ALLOW_NO_DEVICE=true
#export ALLOW_NO_DEVICE

View file

@ -30,53 +30,82 @@
#
# If you have a UPS called snoopy, your section header would be "[snoopy]".
# On a system called "doghouse", the line in your upsmon.conf to monitor
# it would look something like this:
# and manage it would look something like this:
#
# MONITOR snoopy@doghouse 1 upsmonuser mypassword master
# MONITOR snoopy@doghouse 1 upsmonuser mypassword primary
#
# It might look like this if monitoring in slave mode:
# 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 slave
# MONITOR snoopy@doghouse 1 upsmonuser mypassword secondary
#
# Configuration directives
# ------------------------
#
# These directives are common to all drivers that support ups.conf:
# These directives are used by upsdrvctl only and should be specified outside
# of a driver definition:
#
# driver: REQUIRED. Specify the program to run to talk to this UPS.
# apcsmart, bestups, and sec are some examples.
# maxretry: OPTIONAL. Specify the number of attempts to start the driver(s),
# in case of failure, before giving up. A delay of 'retrydelay' is
# inserted between each attempt. Caution should be taken when using
# this option, since it can impact the time taken by your system to
# start.
#
# port: REQUIRED. The serial port where your UPS is connected.
# /dev/ttyS0 is usually the first port on Linux boxes, for example.
# The built-in default is 1 attempt.
#
# sdorder: optional. When you have multiple UPSes on your system, you
# usually need to turn them off in a certain order. upsdrvctl
# shuts down all the 0s, then the 1s, 2s, and so on. To exclude
# a UPS from the shutdown sequence, set this to -1.
# retrydelay: OPTIONAL. Specify the delay between each restart attempt of the
# driver(s), as specified by 'maxretry'. Caution should be taken
# when using this option, since it can impact the time taken by your
# system to start.
#
# The default value for this parameter is 0.
# The default is 5 seconds.
#
# nolock: optional, and not recommended for use in this file.
# chroot: OPTIONAL. Used for securing. See man page for details.
#
# If you put nolock in here, the driver will not lock the
# serial port every time it starts. This may allow other
# processes to seize the port if you start more than one by
# mistake.
# driverpath: OPTIONAL. Used for custom setups. See man page for details.
#
# This is only intended to be used on systems where locking
# absolutely must be disabled for the software to work.
# nowait: OPTIONAL. Tell upsdrvctl to not wait at all for the driver(s)
# to execute the requested command. Fire and forget.
#
# maxstartdelay: optional. This can be set as a global variable
# pollinterval: OPTIONAL. The status of the UPS will be refreshed after a
# maximum delay which is controlled by this setting (default
# 2 seconds). This may be useful if the driver is creating too
# much of a load on your system or network.
# Note that some drivers also have an option called *pollfreq*
# which controls how frequently some of the less critical
# parameters are polled. See respective driver man pages.
#
# Set maxretry to 3 by default, this should mitigate race with slow devices:
maxretry = 3
# These directives can be set outside and inside a driver definition, with
# slightly different meanings per context:
#
# maxstartdelay: OPTIONAL. This can be set as a global variable
# above your first UPS definition and it can also be
# set in a UPS section. This value controls how long
# upsdrvctl will wait for the driver to finish starting.
# This keeps your system from getting stuck due to a
# broken driver or UPS.
#
# The default is 45 seconds.
#
# synchronous: optional. The driver work by default in asynchronous
# mode (i.e *synchronous=no*). This means that all data
# debug_min: OPTIONAL. Specify a minimum debug level for all driver daemons
# (when specified at global level), or for this driver daemon
# (when specified in a driver section), e.g. for troubleshooting
# a deployment. This does not directly impact the foreground or
# background running mode. If both the global and driver level
# `debug_min` are set, the driver-level setting takes precedence.
# Command-line option `-D` can only increase this verbosity level.
#
# user, group: OPTIONAL. Overrides the compiled-in (also global-section,
# when used in driver section) default unprivileged user/group
# name for NUT device driver. Impacts access rights used for
# the socket file access (group) and communication ports (user).
#
# synchronous: OPTIONAL. The driver work by default in asynchronous
# mode (like *no*) with fallback to synchronous if sending
# fails (i.e *synchronous=auto*). This means that all data
# are pushed by the driver on the communication socket to
# upsd (Unix socket on Unix, Named pipe on Windows) without
# waiting for these data to be actually consumed. With
@ -91,6 +120,60 @@
# The default is 'no' (i.e. asynchronous mode) for backward
# compatibility of the driver behavior.
#
# These directives are common to all drivers that support ups.conf:
#
# driver: REQUIRED. Specify the program to run to talk to this UPS.
# apcsmart, bestups, and sec are some examples.
#
# port: REQUIRED. The serial port where your UPS is connected.
# /dev/ttyS0 is usually the first port on Linux boxes, for example.
#
# sdorder: OPTIONAL. When you have multiple UPSes on your system, you
# usually need to turn them off in a certain order. upsdrvctl
# shuts down all the 0s, then the 1s, 2s, and so on. To exclude
# a UPS from the shutdown sequence, set this to -1.
#
# The default value for this parameter is 0.
#
# desc: optional, to keep a note of the UPS purpose, location, etc.
#
# nolock: optional, and not recommended for use in this file.
#
# If you put nolock in here, the driver will not lock the
# serial port every time it starts. This may allow other
# processes to seize the port if you start more than one by
# mistake.
#
# This is only intended to be used on systems where locking
# absolutely must be disabled for the software to work.
#
# ignorelb: OPTIONAL. Ignore low battery condition reported by device,
# and evaluate remaining battery charge or runtime instead.
# See man page for details.
#
# usb_set_altinterface(=num): OPTIONAL. Require that NUT calls this method
# to set the interface, even if 0 (default). Some devices require
# the call to initialize; others however can get stuck due to it -
# so it is not called by default. Yet others can be composite
# devices which use a non-zero interface to represent the UPS.
#
# default.<variable>: OPTIONAL. Set a default value for <variable> which is
# used in case the UPS doesn't provide a value, but which will be
# overwritten if a value is available from the UPS, e.g.:
# default.input.voltage.nominal = 230
# will report the nominal input voltage to be 230, unless the UPS
# eventually tells us differently.
#
# override.<variable>: OPTIONAL. Set a value for <value> that overrides
# (for NUT) any value that may be read from the UPS.
# Used for overriding values from the UPS that are clearly wrong
# (e.g. some devices report wrong values for battery voltage):
# override.battery.voltage.nominal = 12
# Use with caution! This will only change the appearance of the
# variable to the outside world (and NUT calculations), internally
# in the UPS the original value is used.
#
# Anything else is passed through to the hardware-specific part of
# the driver.
#

View file

@ -5,6 +5,8 @@
# It should only be readable by the user that upsd becomes. See the FAQ.
#
# Each entry below provides usage and default value.
#
# For more information, refer to upsd.conf manual page.
# =======================================================================
# MAXAGE <seconds>
@ -19,6 +21,29 @@
# the data fresh within the normal 15 second interval. Watch the syslog
# for notifications from upsd about staleness.
# =======================================================================
# TRACKINGDELAY <seconds>
# TRACKINGDELAY 3600
#
# This defaults to 1 hour. When instant commands and variables setting status
# tracking is enabled, status execution information are kept during this
# amount of time, and then cleaned up.
# =======================================================================
# ALLOW_NO_DEVICE <Boolean>
# ALLOW_NO_DEVICE true
#
# Normally upsd requires that at least one device section is defined in ups.conf
# when the daemon starts, to serve its data. For automatically managed services
# it may be preferred to have upsd always running, and reload the configuration
# when power devices become defined.
#
# Boolean values 'true', 'yes', 'on' and '1' mean that the server would not
# refuse to start with zero device sections found in ups.conf.
#
# Boolean values 'false', 'no', 'off' and '0' mean that the server should refuse
# to start if zero device sections were found in ups.conf. This is the default.
# =======================================================================
# STATEPATH <path>
# STATEPATH /var/run/nut
@ -27,15 +52,17 @@
# than the default that was compiled into the program.
# =======================================================================
# LISTEN <address> [<port>]
# LISTEN <IP address or name> [<port>]
# LISTEN 127.0.0.1 3493
# LISTEN ::1 3493
# 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.
#
# You may specify each interface you want upsd to listen on for connections,
# optionally with a port number.
# You may specify each interface IP address or name that you want upsd to
# listen on for connections, 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
@ -74,7 +101,7 @@
#
# When compiled with SSL support with NSS backend,
# you can enter the certificate path here.
# Certificates are stored in a dedicated database (splitted in 3 files).
# Certificates are stored in a dedicated database (split into 3 files).
# Specify the path of the database directory.
#
# See 'docs/security.txt' or the Security chapter of NUT user manual
@ -107,3 +134,35 @@
# See 'docs/security.txt' or the Security chapter of NUT user manual
# for more information on the SSL support in NUT.
# =======================================================================
# DISABLE_WEAK_SSL <Boolean>
# DISABLE_WEAK_SSL true
#
# Tell upsd to disable older/weak SSL/TLS protocols and ciphers.
#
# With relatively recent versions of OpenSSL or NSS it will be restricted
# to TLSv1.2 or better.
#
# Unless you have really ancient clients, you probably want to enable this.
# Currently disabled by default to ensure compatibility with existing setups.
# =======================================================================
# DEBUG_MIN <Integer>
# DEBUG_MIN 2
#
# Optionally specify a minimum debug level for `upsd` data daemon, e.g. for
# troubleshooting a deployment, without impacting foreground or background
# running mode directly, and without need to edit init-scripts or service
# unit definitions. Note that command-line option `-D` can only increase
# this verbosity level.
#
# NOTE: if the running daemon receives a `reload` command, presence of the
# `DEBUG_MIN NUMBER` value in the configuration file can be used to tune
# debugging verbosity in the running service daemon (it is recommended to
# comment it away or set the minimum to explicit zero when done, to avoid
# huge journals and I/O system abuse). Keep in mind that for this run-time
# tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
# is applied instantly and overrides any previously set value, from file
# or CLI options, regardless of older logging level being higher or lower
# than the newly found number; a missing (or commented away) value however
# does not change the previously active logging verbosity.

View file

@ -63,10 +63,13 @@
#
# [upsmon]
# password = pass
# upsmon master
# upsmon primary
# or
# upsmon slave
# upsmon secondary
#
# The matching MONITOR line in your upsmon.conf would look like this:
#
# MONITOR myups@localhost 1 upsmon pass master (or slave)
# MONITOR myups@localhost 1 upsmon 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.

View file

@ -9,8 +9,8 @@
# waits to run the SHUTDOWNCMD. The other one switches to another userid
# and does everything else.
#
# The default nonprivileged user is set at compile-time with
# 'configure --with-user=...'.
# The default unprivileged user is set at compile-time with the option
# 'configure --with-user=...'
#
# You can override it with '-u <user>' when starting upsmon, or just
# define it here for convenience.
@ -30,7 +30,7 @@
# RUN_AS_USER @RUN_AS_USER@
# --------------------------------------------------------------------------
# MONITOR <system> <powervalue> <username> <password> ("master"|"slave")
# MONITOR <system> <powervalue> <username> <password> ("primary"|"secondary")
#
# List systems you want to monitor. Not all of these may supply power
# to the system running upsmon, but if you want to watch it, it has to
@ -55,33 +55,66 @@
# identifier for it would be "snoopy@doghouse".
#
# <powervalue> is an integer - the number of power supplies that this UPS
# feeds on this system. Most computers only have one power supply, so this
# is normally set to 1. You need a pretty big or special box to have any
# other value here.
# feeds on this system. Most personal computers only have one power supply,
# so this value is normally set to 1, while most modern servers have at least
# two. You need a pretty big or special box to have any other value here.
#
# You can also set this to 0 for a system that doesn't supply any power,
# but you still want to monitor. Use this when you want to hear about
# changes for a given UPS without shutting down when it goes critical,
# unless <powervalue> is 0.
# You can also set this to 0 for a system that doesn't take any power
# from the MONITORed supply, which you still want to monitor (e.g. for an
# administrative workstation fed from a different circuit than the datacenter
# servers it monitors). Use <powervalue> if 0 when you want to hear about
# changes for a given UPS without shutting down when it goes critical.
#
# <username> and <password> must match an entry in that system's
# upsd.users. If your username is "monmaster" and your password is
# upsd.users. If your username is "upsmon" and your password is
# "blah", the upsd.users would look like this:
#
# [monmaster]
# [upsmon]
# password = blah
# upsmon master (or slave)
# upsmon primary # (or secondary)
#
# "master" means this system will shutdown last, allowing the slaves
# time to shutdown first.
# "primary" means this system will shutdown last, allowing the secondary
# systems time to shutdown first.
#
# "slave" means this system shuts down immediately when power goes critical.
# "secondary" means this system shuts down immediately when power goes
# critical and less than MINSUPPLIES power sources have reliable input feeds.
#
# The general assumption is that the "primary" system is the one with direct
# connection to an UPS (such as serial or USB cable), so the primary system
# runs the NUT driver and 'upsd' server locally and can manage the device,
# and it would often tell the UPS to completely power itself off as a step
# in power-race avoidance (see POWERDOWNFLAG for details).
#
# Also, since the primary system stays up the longest, it suffers higher risks
# of ungraceful shutdown if the estimation of remaining runtime (or of the
# time it takes to shut down this system) was guessed wrong. By consequence,
# the "secondary" systems typically monitor the power environment state
# through the 'upsd' processes running on the remote (often "primary") systems
# and do not directly interact with an UPS (no local NUT drivers are running
# on the secondary systems). As such, secondaries typically shut down as
# soon as there is a sufficiently long power outage, or a low-battery alert
# from the UPS, or a loss of connection to the primary while the power was
# last known to be missing.
#
# This assumption and configuration can also make sense for networked UPSes,
# where a rack full of servers might overload the communications capacity
# of the networked management card on the UPS - in this case you might either
# reduce the 'snmp-ups' or 'netxml-ups' driver polling rate, or dedicate a
# "primary" server and set up the rest as "secondary" systems.
#
# In case of such large setups as mentioned above, beware also that shutdown
# times of the rack done all at once can substantially differ from smaller
# scale experiments with single-server shutdowns, since systems can compete
# for shared storage and other limited resources as they go down (and also
# not everyone may safely shut down simultaneously - e.g. a NAS or DB server
# would better go down after all its clients). You would be well served by
# higher-end UPSes with manageable thresholds to declare a critical state.
#
# Examples:
#
# MONITOR myups@bigserver 1 monmaster blah master
# MONITOR su700@server.example.com 1 upsmon secretpass slave
# MONITOR myups@localhost 1 upsmon pass master (or slave)
# 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)
# --------------------------------------------------------------------------
# MINSUPPLIES <num>
@ -91,7 +124,7 @@
# put "1" in this field.
#
# Large/expensive server type systems usually have more, and can run with
# a few missing. The HP NetServer LH4 can run with 2 out of 4, for example,
# a few missing. Some of these can run with 2 out of 4, for example,
# so you'd set that to 2. The idea is to keep the box running as long
# as possible, right?
#
@ -106,7 +139,15 @@ MINSUPPLIES 1
#
# upsmon runs this command when the system needs to be brought down.
#
# This should work just about everywhere ... if it doesn't, well, change it.
# This should work just about everywhere ... if it doesn't, well, change it,
# perhaps to a more complicated custom script.
#
# Note that while you experiment with the initial setup and want to test how
# your configuration reacts to power state changes and ultimately when power
# is reported to go critical, but do not want your system to actually turn
# off, consider setting the SHUTDOWNCMD temporarily to do something benign -
# such as posting a message with 'logger' or 'wall' or 'mailx'. Do be careful
# to plug the UPS back into the wall in a timely fashion.
SHUTDOWNCMD "/sbin/shutdown -h +0"
@ -115,15 +156,22 @@ SHUTDOWNCMD "/sbin/shutdown -h +0"
#
# upsmon calls this to send messages when things happen
#
# This command is called with the full text of the message as one argument.
# This command is called with the full text of the message (from NOTIFYMSG)
# as one argument.
#
# The environment string NOTIFYTYPE will contain the type string of
# whatever caused this event to happen.
#
# The environment string UPSNAME will contain the name of the system/device
# that generated the change.
#
# Note that this is only called for NOTIFY events that have EXEC set with
# NOTIFYFLAG. See NOTIFYFLAG below for more details.
#
# Making this some sort of shell script might not be a bad idea. For more
# information and ideas, see docs/scheduling.txt
# Making this some sort of shell script might not be a bad idea.
# Alternately you can use the upssched program as your NOTIFYCMD for some
# more complex setups (e.g. to ease handling of notification storms).
# For more information and ideas, see docs/scheduling.txt
#
# Example:
# NOTIFYCMD @BINDIR@/notifyme
@ -154,17 +202,17 @@ POLLFREQALERT 5
# --------------------------------------------------------------------------
# HOSTSYNC - How long upsmon will wait before giving up on another upsmon
#
# The master upsmon process uses this number when waiting for slaves to
# disconnect once it has set the forced shutdown (FSD) flag. If they
# don't disconnect after this many seconds, it goes on without them.
# The primary upsmon process uses this number when waiting for secondary
# systems to disconnect once it has set the forced shutdown (FSD) flag.
# If they don't disconnect after this many seconds, it goes on without them.
#
# Similarly, upsmon slave processes wait up to this interval for the
# master upsmon to set FSD when a UPS they are monitoring goes critical -
# that is, on battery and low battery. If the master doesn't do its job,
# the slaves will shut down anyway to avoid damage to the file systems.
# Similarly, upsmon secondary processes wait up to this interval for the
# primary upsmon to set FSD when an UPS they are monitoring goes critical -
# that is, on battery and low battery. If the primary doesn't do its job,
# the secondaries will shut down anyway to avoid damage to the file systems.
#
# This "wait for FSD" is done to avoid races where the status changes
# to critical and back between polls by the master.
# to critical and back between polls by the primary.
HOSTSYNC 15
@ -188,11 +236,12 @@ HOSTSYNC 15
DEADTIME 15
# --------------------------------------------------------------------------
# POWERDOWNFLAG - Flag file for forcing UPS shutdown on the master system
# POWERDOWNFLAG - Flag file for forcing UPS shutdown on the primary system
#
# upsmon will create a file with this name in master mode when it's time
# upsmon will create a file with this name in primary mode when it's time
# to shut down the load. You should check for this file's existence in
# your shutdown scripts and run 'upsdrvctl shutdown' if it exists.
# your shutdown scripts and run 'upsdrvctl shutdown' if it exists, to tell
# the UPS(es) to power off.
#
# See the config-notes.txt file in the docs subdirectory for more information.
# Refer to the section:
@ -226,7 +275,7 @@ POWERDOWNFLAG /etc/killpower
# ONLINE : UPS is back online
# ONBATT : UPS is on battery
# LOWBATT : UPS has a low battery (if also on battery, it's "critical")
# FSD : UPS is being shutdown by the master (FSD = "Forced Shutdown")
# FSD : UPS is being shutdown by the primary (FSD = "Forced Shutdown")
# COMMOK : Communications established with the UPS
# COMMBAD : Communications lost to the UPS
# SHUTDOWN : The system is being shutdown
@ -287,17 +336,20 @@ NOCOMMWARNTIME 300
# --------------------------------------------------------------------------
# FINALDELAY - last sleep interval before shutting down the system
#
# On a master, upsmon will wait this long after sending the NOTIFY_SHUTDOWN
# On a primary, upsmon will wait this long after sending the NOTIFY_SHUTDOWN
# before executing your SHUTDOWNCMD. If you need to do something in between
# those events, increase this number. Remember, at this point your UPS is
# almost depleted, so don't make this too high.
# almost depleted, so don't make this too high. If needed, on high-end UPS
# devices you can usually configure when the low-battery state is announced
# based on estimated remaining run-time or on charge level of the batteries.
#
# Alternatively, you can set this very low so you don't wait around when
# it's time to shut down. Some UPSes don't give much warning for low
# battery and will require a value of 0 here for a safe shutdown.
#
# Note: If FINALDELAY on the slave is greater than HOSTSYNC on the master,
# the master will give up waiting for the slave to disconnect.
# Note: If FINALDELAY on the secondary is greater than HOSTSYNC on the
# primary, the primary will give up waiting for that secondary system
# to disconnect.
FINALDELAY 5
@ -307,7 +359,7 @@ FINALDELAY 5
# When compiled with SSL support, you can enter the certificate path here.
#
# With NSS:
# Certificates are stored in a dedicated database (splitted in 3 files).
# Certificates are stored in a dedicated database (split into 3 files).
# Specify the path of the database directory.
#
# CERTPATH @CONFPATH@/cert/upsmon
@ -362,7 +414,7 @@ FINALDELAY 5
# This effectively forces the use of SSL, so don't use this unless
# all of your upsd hosts are ready for SSL and have their certificates
# in order.
# When compiled with NSS support of SSL, can be overriden for host
# When compiled with NSS support of SSL, can be overridden for host
# specified with a CERTHOST directive.
@ -376,5 +428,26 @@ FINALDELAY 5
# that nobody can sniff your sessions without a large effort. Setting
# this will make upsmon drop connections if the remote upsd doesn't
# support SSL, so don't use it unless all of them have it running.
# When compiled with NSS support of SSL, can be overriden for host
# When compiled with NSS support of SSL, can be overridden for host
# specified with a CERTHOST directive.
# --------------------------------------------------------------------------
# DEBUG_MIN - specify minimal debugging level for upsmon daemon
# e.g. DEBUG_MIN 6
#
# Optionally specify a minimum debug level for `upsmon` daemon, e.g. for
# troubleshooting a deployment, without impacting foreground or background
# running mode directly, and without need to edit init-scripts or service
# unit definitions. Note that command-line option `-D` can only increase
# this verbosity level.
#
# NOTE: if the running daemon receives a `reload` command, presence of the
# `DEBUG_MIN NUMBER` value in the configuration file can be used to tune
# debugging verbosity in the running service daemon (it is recommended to
# comment it away or set the minimum to explicit zero when done, to avoid
# huge journals and I/O system abuse). Keep in mind that for this run-time
# tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
# is applied instantly and overrides any previously set value, from file
# or CLI options, regardless of older logging level being higher or lower
# than the newly found number; a missing (or commented away) value however
# does not change the previously active logging verbosity.

View file

@ -83,9 +83,15 @@ CMDSCRIPT @BINDIR@/upssched-cmd
# argument.
#
# Example:
# Start a timer that'll execute when any UPS (*) has been gone 10 seconds
# 1) Start a timer that will execute when communication with any UPS (*) has
# been gone for 10 seconds
#
# AT COMMBAD * START-TIMER upsgone 10
#
# 2) Start a timer that will execute when any UPS (*) has been running
# on battery for 30 seconds
#
# AT ONBATT * START-TIMER onbattwarn 30
# -----------------------------------------------------------------------
#
@ -95,10 +101,15 @@ CMDSCRIPT @BINDIR@/upssched-cmd
# has passed then pass the optional argument <cmd> to CMDSCRIPT.
#
# Example:
# If a specific UPS (myups@localhost) comes back online, then stop the
# timer before it triggers
# 1) If a specific UPS (myups@localhost) communication is restored, then stop
# the timer before it triggers
#
# AT COMMOK myups@localhost CANCEL-TIMER upsgone
#
# 2) If any UPS (*) reverts to utility power, then stop the timer before it
# triggers
#
# AT ONLINE * CANCEL-TIMER onbattwarn
# -----------------------------------------------------------------------
#

View file

@ -17,8 +17,8 @@
@UPSSTATSPATH upsstats.cgi@
@UPSIMAGEPATH upsimage.cgi@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
@ -26,10 +26,16 @@
@REFRESH@
<title>@HOSTDESC@ : @VAR ups.model@ on @HOST@</title>
<!-- LINK REL="stylesheet" TYPE="text/css" HREF="http://localhost/nut/nut.css" / -->
<style type="text/css">
body{color:#00fc00; background:#808080; font-family:"Times New Roman", Times, serif;}
a:link{color:#00e;}
a:visited{color:#551a8b;}
table{background:#000;}
</style>
</head>
<body BGCOLOR="#808080" TEXT="#00FC00" LINK="#0000EE" VLINK="#551A8B">
<body>
<table BORDER="1" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="10" BGCOLOR="#000000">
<table style="margin:auto" BORDER="1" CELLSPACING="0" CELLPADDING="10">
<tr>
<th COLSPAN="20">Network UPS Tools upsstats @VERSION@ - @HOSTDESC@ - @VAR ups.model@ on @HOST@</th>
@ -51,7 +57,7 @@
<tr>
<td BGCOLOR="#000000" VALIGN="TOP">
<td VALIGN="TOP">
<table BORDER="0"> <!-- table 2 -->
@ -195,7 +201,7 @@
@IFSUPP ambient.temperature@
@IFSUPP ambient.humidity@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
<td ALIGN="CENTER">Temperature<br>@IMG ambient.temperature tempmin=0 tempmax=50 width=90@</td>
<td ALIGN="CENTER">Humidity<br>@IMG ambient.humidity width=90@</td>
@ -203,21 +209,21 @@
</td>
@ELSE@
@IFSUPP ambient.temperature@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
<td ALIGN="CENTER">Temperature<br>@IMG ambient.temperature tempmin=0 tempmax=50@</td>
</tr></table>
</td>
@ELSE@
@IFSUPP ambient.humidity@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
<td ALIGN="CENTER">Humidity<br>@IMG ambient.humidity@</td>
</tr></table>
</td>
@ENDIF@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
@IFSUPP battery.charge@
@IFSUPP battery.voltage@
@ -232,7 +238,7 @@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
@IFSUPP input.L2-L3.voltage@
<td ALIGN="CENTER">L1-L2<br>@IMG input.L1-L2.voltage width=68@</td>
@ -249,7 +255,7 @@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
@IFSUPP output.L2-L3.voltage@
<td ALIGN="CENTER">L1-L2<br>@IMG output.L1-L2.voltage width=68@</td>
@ -266,7 +272,7 @@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<td ALIGN="CENTER" VALIGN="TOP">
<table BORDER="0"><tr>
@IFSUPP output.L2.power.percent@
<td ALIGN="CENTER">L1<br>@IMG output.L1.power.percent width=68@</td>
@ -286,9 +292,12 @@
</tr>
</table>
<a href="http://validator.w3.org/check?uri=referer"><img style="float:right"
src="http://www.w3.org/Icons/valid-html40"
alt="Valid HTML 4.0 Transitional" height="31" width="88"></a>
<div><a href="https://jigsaw.w3.org/css-validator/check/referer"><img
style="float:right" src="https://jigsaw.w3.org/css-validator/images/vcss"
alt="Valid CSS" title="Valid CSS" height="31" width="88"></a>
<a href="https://validator.w3.org/check?uri=referer"><img
style="float:right" src="https://www.w3.org/Icons/valid-html401"
alt="Valid HTML 4.01 Strict" title="Valid HTML 4.01 Strict"
height="31" width="88"></a></div>
</body>
</html>

View file

@ -16,8 +16,8 @@
@UPSSTATSPATH upsstats.cgi@
@UPSIMAGEPATH upsimage.cgi@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
@ -28,21 +28,29 @@ Network UPS Tools upsstats
@VERSION@
: UPS Status
</title>
<style type="text/css">
body{font-family:"Times New Roman", Times, serif;}
a:link{color:#00e;}
a:visited{color:#551a8b;}
th, td{padding:0.5ex;}
.t1{background:#0ff;}
.t2{background:#0f0;}
</style>
<!-- link rel="stylesheet" type="text/css" href="nut.css" / -->
@REFRESH@
</head>
<body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000EE" VLINK="#551A8B">
<body>
<table BGCOLOR="#50A0A0" ALIGN="CENTER">
<table style="margin:auto; background:#50A0A0; text-align:center;">
<tr><td>
<table CELLPADDING="5">
<table>
<tr>
<th COLSPAN="10" BGCOLOR="#60B0B0">
<th COLSPAN="10" style="background:#60B0B0;">
<font SIZE="+2">Network UPS Tools upsstats
<span style="font-size:1.5em">Network UPS Tools upsstats
@VERSION@
</font>
</span>
<br>
@DATE %a %b %d %X %Z %Y@
@ -50,7 +58,7 @@ Network UPS Tools upsstats
</tr>
<tr BGCOLOR="#60B0B0">
<tr style="background:#60B0B0;">
<th COLSPAN="1">System</th>
<th COLSPAN="1">Model</th>
<th COLSPAN="1">Status</th>
@ -65,20 +73,20 @@ Network UPS Tools upsstats
@FOREACHUPS@
<tr ALIGN=CENTER>
<td BGCOLOR="#00FFFF">
<tr>
<td class="t1">
@HOSTLINK@
</td>
<td BGCOLOR="#00FFFF">
<td class="t1">
@VAR ups.model@
</td>
<td BGCOLOR="@STATUSCOLOR@">
<td style="background:@STATUSCOLOR@">
@STATUS@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@IFSUPP battery.charge@
@VAR battery.charge@
%
@ -89,18 +97,18 @@ Network UPS Tools upsstats
@IFBETWEEN input.transfer.low input.transfer.high input.L1-L2.voltage@
@IFBETWEEN input.transfer.low input.transfer.high input.L2-L3.voltage@
@IFBETWEEN input.transfer.low input.transfer.high input.L3-L1.voltage@
<td BGCOLOR="#00FF00">
<td class="t2">
@ELSE@
@IFSUPP input.L2-N.voltage@
@IFBETWEEN input.transfer.low input.transfer.high input.L1-N.voltage@
@IFBETWEEN input.transfer.low input.transfer.high input.L2-N.voltage@
@IFBETWEEN input.transfer.low input.transfer.high input.L3-N.voltage@
<td BGCOLOR="#00FF00">
<td class="t2">
@ELSE@
@IFBETWEEN input.transfer.low input.transfer.high input.voltage@
<td BGCOLOR="#00FF00">
<td class="t2">
@ELSE@
<td BGCOLOR="#FF0000">
<td style="background:red;">
@ENDIF@
@IFSUPP input.L2-L3.voltage@
@ -118,7 +126,7 @@ Network UPS Tools upsstats
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@IFSUPP output.L2-L3.voltage@
@VAR output.L1-L2.voltage@
@VAR output.L2-L3.voltage@
@ -134,7 +142,7 @@ Network UPS Tools upsstats
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@IFSUPP output.L2.power.percent@
@VAR output.L1.power.percent@
@VAR output.L2.power.percent@
@ -151,7 +159,7 @@ Network UPS Tools upsstats
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@IFSUPP ups.temperature@
@UPSTEMP@
@DEGREES@
@ -162,13 +170,13 @@ Network UPS Tools upsstats
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@IFSUPP battery.runtime@
@RUNTIME@
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
<td class="t2">
@TREELINK@
</td>
</tr>
@ -180,11 +188,9 @@ Network UPS Tools upsstats
</td></tr>
</table>
<hr /><div><small>
<a href="http://jigsaw.w3.org/css-validator/check/referer"><img style="float:right" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" height="31" width="88"/></a>
<a href="http://validator.w3.org/check?uri=referer"><img style="float:right"
src="http://www.w3.org/Icons/valid-html40"
alt="Valid HTML 4.0 Transitional" height="31" width="88"></a>
<hr><div><small>
<a href="https://jigsaw.w3.org/css-validator/check/referer"><img style="float:right" src="https://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" height="31" width="88"></a>
<a href="https://validator.w3.org/check?uri=referer"><img style="float:right" src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Strict" height="31" width="88"></a>
</small></div>
</body></html>

690
config.guess vendored

File diff suppressed because it is too large Load diff

310
config.sub vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2014 Free Software Foundation, Inc.
# Copyright 1992-2018 Free Software Foundation, Inc.
timestamp='2014-09-11'
timestamp='2018-02-22'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -15,7 +15,7 @@ timestamp='2014-09-11'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -25,7 +25,7 @@ timestamp='2014-09-11'
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@ -33,7 +33,7 @@ timestamp='2014-09-11'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@ -53,12 +53,11 @@ timestamp='2014-09-11'
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Operation modes:
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2014 Free Software Foundation, Inc.
Copyright 1992-2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -95,7 +94,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
echo "$1"
exit ;;
* )
@ -113,24 +112,24 @@ esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | cloudabi*-eabi* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
if [ "$basic_machine" != "$1" ]
then os=`echo "$1" | sed 's/.*-/-/'`
else os=; fi
;;
esac
@ -179,44 +178,44 @@ case $os in
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
@ -228,10 +227,7 @@ case $os in
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
;;
-psos*)
os=-psos
@ -255,15 +251,16 @@ case $basic_machine in
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| ba \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| e2k | epiphany \
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| i370 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
@ -299,13 +296,14 @@ case $basic_machine in
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| pdp10 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pru \
| pyramid \
| riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@ -313,7 +311,8 @@ case $basic_machine in
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| visium \
| wasm32 \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
@ -327,11 +326,14 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
leon|leon[3-9])
basic_machine=sparc-$basic_machine
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
;;
ms1)
basic_machine=mt-unknown
@ -360,7 +362,7 @@ case $basic_machine in
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
@ -372,17 +374,18 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| ba-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| e2k-* | elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
@ -423,13 +426,15 @@ case $basic_machine in
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pru-* \
| pyramid-* \
| riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
@ -437,6 +442,8 @@ case $basic_machine in
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
| wasm32-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@ -450,7 +457,7 @@ case $basic_machine in
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
basic_machine=i386-pc
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
@ -484,7 +491,7 @@ case $basic_machine in
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
@ -513,6 +520,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
asmjs)
basic_machine=asmjs-unknown
;;
aux)
basic_machine=m68k-apple
os=-aux
@ -526,7 +536,7 @@ case $basic_machine in
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
@ -534,13 +544,13 @@ case $basic_machine in
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
@ -629,10 +639,18 @@ case $basic_machine in
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
dpx2*)
basic_machine=m68k-bull
os=-sysv3
;;
e500v[12])
basic_machine=powerpc-unknown
os=$os"spe"
;;
e500v[12]-*)
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=$os"spe"
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
@ -722,9 +740,6 @@ case $basic_machine in
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
@ -737,26 +752,26 @@ case $basic_machine in
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
vsta)
basic_machine=i386-unknown
os=-vsta
;;
@ -774,17 +789,17 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
leon-*|leon[3-9]-*)
basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
@ -816,10 +831,10 @@ case $basic_machine in
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
@ -838,7 +853,7 @@ case $basic_machine in
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
@ -880,7 +895,7 @@ case $basic_machine in
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
next | m*-next)
basic_machine=m68k-next
case $os in
-nextstep* )
@ -925,6 +940,12 @@ case $basic_machine in
nsr-tandem)
basic_machine=nsr-tandem
;;
nsv-tandem)
basic_machine=nsv-tandem
;;
nsx-tandem)
basic_machine=nsx-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
@ -957,7 +978,7 @@ case $basic_machine in
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
@ -973,7 +994,7 @@ case $basic_machine in
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
@ -988,16 +1009,16 @@ case $basic_machine in
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
@ -1007,23 +1028,23 @@ case $basic_machine in
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
ppcle | powerpclittle)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
ppc64le | powerpc64little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
@ -1077,17 +1098,10 @@ case $basic_machine in
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
@ -1106,7 +1120,7 @@ case $basic_machine in
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
@ -1228,6 +1242,9 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
x64)
basic_machine=x86_64-pc
;;
xbox)
basic_machine=i686-pc
os=-mingw32
@ -1236,20 +1253,12 @@ case $basic_machine in
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@ -1278,10 +1287,6 @@ case $basic_machine in
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
@ -1291,9 +1296,6 @@ case $basic_machine in
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
@ -1313,7 +1315,7 @@ case $basic_machine in
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
exit 1
;;
esac
@ -1321,10 +1323,10 @@ esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
;;
*)
;;
@ -1335,8 +1337,8 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases that might get confused
# with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
@ -1347,45 +1349,48 @@ case $os in
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# es1800 is here to avoid being matched by es* (a different OS)
-es1800*)
os=-ose
;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# Each alternative MUST end in a * to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -morphos* | -superux* | -rtmk* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
| -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
| -midnightbsd*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@ -1402,12 +1407,12 @@ case $os in
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
-sim | -xray | -os68k* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
os=`echo "$os" | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
@ -1416,10 +1421,10 @@ case $os in
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
@ -1430,12 +1435,6 @@ case $os in
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
@ -1460,7 +1459,7 @@ case $os in
-nova*)
os=-rtmk-nova
;;
-ns2 )
-ns2)
os=-nextstep2
;;
-nsk*)
@ -1482,7 +1481,7 @@ case $os in
-oss*)
os=-sysv3
;;
-svr4)
-svr4*)
os=-sysv4
;;
-svr3)
@ -1497,32 +1496,38 @@ case $os in
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-pikeos*)
# Until real need of OS specific support for
# particular features comes up, bare metal
# configurations are quite functional.
case $basic_machine in
arm*)
os=-eabi
;;
*)
os=-elf
;;
esac
;;
-nacl*)
;;
-ios)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
exit 1
;;
esac
@ -1612,12 +1617,12 @@ case $basic_machine in
sparc-* | *-sun)
os=-sunos4.1.1
;;
pru-*)
os=-elf
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
@ -1657,7 +1662,7 @@ case $basic_machine in
m88k-omron*)
os=-luna
;;
*-next )
*-next)
os=-nextstep
;;
*-sequent)
@ -1672,9 +1677,6 @@ case $basic_machine in
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
@ -1784,15 +1786,15 @@ case $basic_machine in
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
echo "$basic_machine$os"
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'write-file-functions 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"

22304
configure vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -5,3 +5,16 @@ SUBDIRS = html
dist_data_DATA = cmdvartab
nodist_data_DATA = driver.list
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)" $@
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)" $@
spellcheck spellcheck-interactive spellcheck-sortdict:
$(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="cmdvartab" SPELLCHECK_DIR="$(srcdir)" $@
MAINTAINERCLEANFILES = Makefile.in .dirstamp
CLEANFILES = *.pdf *.html *-spellchecked

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -17,7 +17,17 @@
# Network UPS Tools: data
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -82,19 +92,24 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = data
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/driver.list.in $(dist_data_DATA)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -103,11 +118,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(dist_data_DATA) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = driver.list
@ -175,7 +197,7 @@ am__recursive_targets = \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
distdir distdir-am
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
@ -196,6 +218,7 @@ am__define_uniq_tagged_files = \
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/driver.list.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@ -229,6 +252,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -239,6 +263,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -252,6 +277,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -264,6 +290,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -281,6 +308,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -291,21 +320,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -325,6 +362,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -338,6 +378,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -355,6 +396,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -368,6 +410,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -393,12 +438,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -412,6 +459,8 @@ SUBDIRS = html
dist_data_DATA = cmdvartab
nodist_data_DATA = driver.list
EXTRA_DIST = evolution500.seq epdu-managed.dev
MAINTAINERCLEANFILES = Makefile.in .dirstamp
CLEANFILES = *.pdf *.html *-spellchecked
all: all-recursive
.SUFFIXES:
@ -427,14 +476,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu data/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu data/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -595,7 +643,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -680,6 +731,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@ -688,6 +740,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
@ -771,6 +824,18 @@ uninstall-am: uninstall-dist_dataDATA uninstall-nodist_dataDATA
ps ps-am tags tags-am uninstall uninstall-am \
uninstall-dist_dataDATA uninstall-nodist_dataDATA
.PRECIOUS: Makefile
# 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)" $@
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)" $@
spellcheck spellcheck-interactive spellcheck-sortdict:
$(MAKE) -f $(top_builddir)/docs/Makefile SPELLCHECK_SRC="cmdvartab" SPELLCHECK_DIR="$(srcdir)" $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View file

@ -84,7 +84,7 @@ VARDESC input.load "Load on (ePDU) input (percent of full)"
VARDESC input.realpower "Current sum value of all (ePDU) phases real power (W)"
VARDESC input.power "Current sum value of all (ePDU) phases apparent power (VA)"
VARDESC input.source "The current input power source"
VARDESC input.source.preferred "The prefered input power source"
VARDESC input.source.preferred "The preferred input power source"
VARDESC output.voltage "Output voltage (V)"
VARDESC output.voltage.nominal "Nominal output voltage (V)"
@ -94,6 +94,7 @@ VARDESC output.current "Output current (A)"
VARDESC output.current.nominal "Nominal output current (A)"
VARDESC battery.charge "Battery charge (percent of full)"
VARDESC battery.charge.approx "Rough approximation of battery charge"
VARDESC battery.charge.low "Remaining battery level when UPS switches to LB (percent)"
VARDESC battery.charge.restart "Minimum battery level for restart after power off (percent)"
VARDESC battery.charge.warning "Battery level when UPS switches to Warning state (percent)"
@ -145,7 +146,7 @@ VARDESC ambient.present "Ambient sensor presence"
VARDESC ambient.contacts.1.status "State of the dry contact sensor 1"
VARDESC ambient.contacts.2.status "State of the dry contact sensor 2"
# FIXME: the outlet collection is indexed - solve with regexs?
# FIXME: the outlet collection is indexed - solve with regexps?
#
# VARDESC outlet.[[:digit:]]+.id "Outlet system identifier (<index>)"
@ -177,6 +178,7 @@ VARDESC outlet.2.delay.start "Interval to wait before restarting this outlet (se
VARDESC driver.name "Driver name"
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"

View file

@ -16,8 +16,8 @@
# ========
# - device type:
# "ups" for Uninterruptible Power Supply
# "pdu" for Power Distributions Unit
# "scd" for Solar Controlers Device
# "pdu" for Power Distribution Unit
# "scd" for Solar Controller Device
# "ats" for Automatic Transfer Switch
#
# - support level: a number from "1" to "5" (stars) meaning:
@ -35,15 +35,25 @@
# Duplicate text in the last field will be cooked out during the conversion
# to HTML with ROWSPAN magic. They must be an exact match for this to work.
"Ablerex" "ups" "2" "MS-RT" "" "blazer_ser"
"Ablerex" "ups" "2" "625L" "USB" "blazer_usb"
"Ablerex" "ups" "2" "Hope Office 400/600" "" "blazer_ser"
"Ablerex" "ups" "2" "MARS MS3000RT" "" "blazer_ser"
"Ablerex" "ups" "2" "MS-RT" "" "blazer_ser"
"Ablerex" "ups" "2" "MP series" "USB" "nutdrv_qx"
"Ablerex" "ups" "2" "ARES Plus series" "USB" "nutdrv_qx"
"Ablerex" "ups" "2" "MSII series" "USB" "nutdrv_qx"
"Ablerex" "ups" "2" "MSIII series" "USB" "nutdrv_qx"
"Ablerex" "ups" "2" "GRs series" "USB" "nutdrv_qx"
"Ablerex" "ups" "2" "GRs Plus series" "USB" "nutdrv_qx"
"ActivePower" "ups" "2" "400VA" "" "blazer_ser"
"ActivePower" "ups" "2" "1400VA" "" "blazer_ser"
"ActivePower" "ups" "2" "2000VA" "" "blazer_ser"
"Advice" "ups" "2" "TopGuard 2000" "" "blazer_ser"
"Advice" "ups" "2" "Top V Pro 6-10K" "USB" "blazer_usb" # https://www.advice.co.il/en/advice-products/ups-systems/ups-online-systems/one-phase-ups-5k-10k/%D7%90%D7%9C-%D7%A4%D7%A1%D7%A7-%D7%90%D7%95%D7%9F-%D7%9C%D7%99%D7%99%D7%9F-top-v-pro-6-10k-detail https://github.com/networkupstools/nut/issues/744
"Advice" "ups" "2" "PRS850" "USB" "blazer_usb"
"Advice" "ups" "2" "PRV700 Pro" "USB" "blazer_usb"
"AEC" "ups" "1" "MiniGuard UPS 700" "Megatec M2501 cable" "genericups upstype=21"
@ -51,6 +61,7 @@
"AEG Power Solutions" "ups" "3" "PROTECT NAS" "" "usbhid-ups"
"AEG Power Solutions" "ups" "3" "PROTECT B" "" "usbhid-ups"
"APC" "ups" "3" "APC AP9584 Serial-to-USB kit" "USB" "usbhid-ups" # Allows USB connections to Serial-port APC devices, https://github.com/networkupstools/nut/pull/181
"APC" "ups" "2" "Back-UPS 1200BR (Microsol)" "" "solis"
"APC" "ups" "2" "Back-UPS BZ2200BI-BR (Microsol)" "" "solis"
"APC" "ups" "1" "Back-UPS Pro" "" "apcsmart"
@ -58,13 +69,16 @@
"APC" "ups" "1" "Smart-UPS" "" "apcsmart"
"APC" "ups" "1" "Smart-UPS SMT/SMX/SURTD" "Microlink models with RJ45 socket - they *require* AP9620 SmartSlot expansion card and smart cable" "apcsmart"
"APC" "ups" "2" "Back-UPS Pro USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS (USB)" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS CS USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS RS USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS LS USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS ES/CyberFort 350" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS BF500" "USB" "usbhid-ups"
"APC" "ups" "2" "BACK-UPS XS LCD" "USB" "usbhid-ups"
"APC" "ups" "2" "Smart-UPS USB" "USB" "usbhid-ups"
"APC" "ups" "2" "Back-UPS XS 1000M (Back-UPS Pro 1000, Model BX1000M)" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/139
"APC" "ups" "2" "SMC2200BI-BR" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/557
"APC" "ups" "2" "Smart-UPS (USB)" "USB" "usbhid-ups"
"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"
@ -77,7 +91,7 @@
"APC" "pdu" "1" "Masterswitch" "940-0020 cable" "genericups upstype=12"
"APC" "pdu" "1" "AP9210" "8 outlets" "powerman-pdu (experimental)"
"APC" "pdu" "1" "AP79xx" "8 to 24 outlets" "powerman-pdu (experimental)"
"APC" "pdu" "3" "(various)" "SNMP monitoring card" "snmp-ups (experimental)"
"APC" "pdu" "3" "(various APxxxx)" "SNMP monitoring card" "snmp-ups"
"APC" "ats" "3" "ATS AP7724" "" "snmp-ups (experimental)"
"Aphel" "pdu" "3" "various PDU" "" "snmp-ups (experimental)"
@ -88,6 +102,8 @@
"Appro" "pdu" "1" "SWPDU" "48 outlets" "powerman-pdu (experimental)"
"ARES" "ups" "2" "AR265i" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 did not explicitly mention the driver parameters, but other reports in the discussion did
"ARTronic" "ups" "2" "ARTon Millenium 1/2/3/6/10 kVA" "Serial" "blazer_ser"
"ARTronic" "ups" "2" "ARTon Millenium 3.1 10/15/20 kVA" "Serial" "blazer_ser"
"ARTronic" "ups" "2" "ARTon Titanium 6/10 kVA" "Serial" "blazer_ser"
@ -98,6 +114,8 @@
"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"
"ASEM SPA" "ups" "5" "PB1300 UPS" "i2c" "asem"
"Asium" "ups" "3" "P700" "USB" "blazer_usb" # http://www.asiumpower.com/Asium-ASIUM-P700-650VA-360W/dp/B009SMEQ10
@ -118,6 +136,7 @@
"Atlantis Land" "ups" "2" "(various)" "USB" "nutdrv_qx"
"Aviem Systems" "ups" "2" "Aviem Power RT 1000-3000VA" "" "blazer_ser"
"Aviem Systems" "ups" "2" "Aviem Pro 2000VA" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/827
"Baytech" "pdu" "1" "RPC3" "8 outlets" "powerman-pdu (experimental)"
"Baytech" "pdu" "1" "RPC3-20NC" "8 outlets" "powerman-pdu (experimental)"
@ -185,45 +204,63 @@
"COVER ENERGY SA" "ups" "2" "COVER PRM 1K/2K/3K/6K/10K EC" "" "blazer_usb"
"COVER ENERGY SA" "ups" "2" "COVER PRM 6K/10K PR" "" "blazer_usb"
"CPC" "ups" "2" "RACK850VA" "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
"Crown" "ups" "2" "CMU-SP1200IEC" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/1014
"Cyber Power Systems" "ups" "1" "550SL" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "1" "725SL" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "1" "CPS1100AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1200AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1250AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1500AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1500AVR-HO" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS320AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS500AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS650AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS700AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS800AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS825VA" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS850AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS900AVR" "" "powerpanel" # http://www.cyberpowersystems.com/products/ups-systems/other-ups/CPS900AVR.html
"Cyber Power Systems" "ups" "1" "CPS1250AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1500AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "Power99" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "1" "550SL" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "1" "725SL" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "1" "CPS825VA" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1100AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1200AVR" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "CPS1500AVR-HO" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "PR2200" "" "powerpanel"
"Cyber Power Systems" "ups" "2" "PR3000E" "" "powerpanel"
"Cyber Power Systems" "ups" "2" "OL3000RMXL2U" "" "powerpanel"
"Cyber Power Systems" "ups" "1" "Power99" "" "genericups upstype=7"
"Cyber Power Systems" "ups" "2" "AE550" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "BL1250U" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/battery-backup/bl1250u/ https://github.com/networkupstools/nut/issues/1012
"Cyber Power Systems" "ups" "2" "BR1000ELCD" "USB" "usbhid-ups" # https://www.cyberpower.com/eu/en/product/sku/BR1000ELCD https://github.com/networkupstools/nut/issues/552
"Cyber Power Systems" "ups" "2" "CP1350AVRLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP1500AVRLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP850PFCLCD" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/605
"Cyber Power Systems" "ups" "2" "CP1500PFCLCD" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/cp1500pfclcd/ https://github.com/networkupstools/nut/issues/520
"Cyber Power Systems" "ups" "2" "CP900AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CPS685AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CPS800AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "AE550" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "CP 1500C" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "CP825AVR-G / LE825G" "USB" "usbhid-ups" # http://www.cyberpowersystems.com/products/ups-systems/retail-products/LE825G.html
"Cyber Power Systems" "ups" "3" "OR2200LCDRM2U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "OR700LCDRM1U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "PR6000LCDRTXL5U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "OL3000RMXL2U" "" "powerpanel"
"Cyber Power Systems" "ups" "2" "PR3000E" "" "powerpanel"
"Cyber Power Systems" "ups" "2" "Value 1500ELCD-RU" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "Value 400E" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "Value 600E" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "Value 800E" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "Value 1500ELCD-RU" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP900AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP1000AVRLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP1350AVRLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP1500AVRLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "2" "CP1000PFCLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "CP 1500C" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "CP1000PFCLCD" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "CP1500EPFCLCD" "USB" "usbhid-ups" # http://www.cyberpower-eu.com/products/ups_systems/pfc-sinewave/cp1500epfclcd.htm
"Cyber Power Systems" "ups" "3" "CP825AVR-G / LE825G" "USB" "usbhid-ups" # http://www.cyberpowersystems.com/products/ups-systems/retail-products/LE825G.html
"Cyber Power Systems" "ups" "3" "EC350G" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/products/ups/ecologic/ec350g
"Cyber Power Systems" "ups" "3" "EC750G" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/products/ups/desktop/ec750g
"Cyber Power Systems" "ups" "3" "EC850LCD" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/ec850lcd/ https://github.com/networkupstools/nut/issues/622
"Cyber Power Systems" "ups" "3" "OR1500ERM1U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/1338
"Cyber Power Systems" "ups" "3" "OR2200LCDRM2U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "OR700LCDRM1U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "OR500LCDRM1U" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/or500lcdrm1u/ https://github.com/networkupstools/nut/issues/578
"Cyber Power Systems" "ups" "3" "RT650EI" "USB" "usbhid-ups" # http://www.cyberpowersystems.de/produkte/backup-usv-serien/rt-serie.html https://github.com/networkupstools/nut/issues/453
"Cyber Power Systems" "ups" "3" "UT2200E" "USB" "usbhid-ups" # https://www.cyberpower.com/ww/en/product/sku/UT2200E https://github.com/networkupstools/nut/issues/556
"Cyber Power Systems" "ups" "3" "PR1500RT2U" "" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/new-smart-app-sinewave/pr1500rt2u/ https://github.com/networkupstools/nut/issues/1191
"Cyber Power Systems" "ups" "3" "PR6000LCDRTXL5U" "USB" "usbhid-ups"
"Cyber Power Systems" "ups" "3" "PR2200LCDRT2U" "" "snmp-ups"
"Cyber Power Systems" "ups" "3" "RMCARD100" "" "snmp-ups"
"Cyber Power Systems" "ups" "3" "RMCARD201" "" "snmp-ups"
"Cyber Power Systems" "ups" "3" "RMCARD202" "" "snmp-ups"
"Cyber Power Systems" "ups" "3" "RMCARD205" "" "snmp-ups"
"Cyber Power Systems" "ups" "3" "RMCARD301" "" "snmp-ups"
"Cyclades" "pdu" "1" "PM8" "8 outlets" "powerman-pdu (experimental)"
@ -253,14 +290,24 @@
"Dell" "ups" "5" "Various (XML/HTTP mode)" "UPS Network Management Card" "netxml-ups (experimental)"
"Delta" "ups" "1" "GES602N" "" "belkin"
"Delta" "ups" "4" "Delta UPS Amplon R Series" "USB port" "usbhid-ups"
"Deltec" "ups" "1" "PowerRite Pro II" "" "genericups upstype=15"
"Deltec" "ups" "4" "PRM 450/700/1000/1500" "" "upscode2"
"DEXP" "ups" "2" "MIX 850VA" "USB" "blazer_usb langid_fix=0x0409 runtimecal=240,100,720,50 default.battery.voltage.high=2.27 default.battery.voltage.low=1.72" # https://github.com/networkupstools/nut/issues/721
"Digital Loggers" "pdu" "1" "LPC, EPCR2, DIN" "8 outlets" "powerman-pdu (experimental)"
"DigiTECH" "ups" "2" "Computer 650VA" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638 caveats at https://github.com/networkupstools/nut/issues/674 (may need longer pollinterval)
"Digitus" "ups" "1" "DN-170014" "USB" "richcomm_usb" # http://www.digitus.info/en/products/professional-network/security-and-surveillance/power-supply/uninterrruptable-power-supplies/ups-uninterruptible-power-systems-dn-170014/section/prof/
"Digitus" "ups" "2" "DN-170020" "" "blazer_ser"
"Digitus" "ups" "2" "DN-170040" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/1251
"Digitus" "ups" "2" "DN-170041" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/1251
"Digitus" "ups" "2" "DN-170040" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1251
"Digitus" "ups" "2" "DN-170041" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1251
"Digitus" "ups" "2" "DN-170076" "USB" "nutdrv_qx" # https://www.digitus.info/en/products/network-and-server-cabinets/power-supply/uninterruptible-power-supplies/dn-170076/ https://github.com/networkupstools/nut/issues/948
"Dynamix" "ups" "2" "UPS1700D" "" "blazer_ser"
"Dynamix" "ups" "2" "UPS-650VA" "" "blazer_ser"
@ -274,6 +321,7 @@
"Eaton" "ups" "5" "Ellipse ECO 650/800/1200/1600 VA" "USB" "usbhid-ups"
"Eaton" "ups" "5" "Ellipse ASR USBS 600/750/1000/1500 VA" "USB cable" "usbhid-ups"
"Eaton" "ups" "5" "Ellipse MAX USBS 600/850/1100/1500 VA" "USB cable" "usbhid-ups"
"Eaton" "ups" "5" "Ellipse PRO 650 VA" "USB cable" "usbhid-ups"
"Eaton" "ups" "5" "Evolution 650/850/1150/1550/2000 VA" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "Evolution S 1250/1750/2500/3000 VA" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "EX 700/1000/1500 VA" "USB port" "usbhid-ups"
@ -284,24 +332,32 @@
"Eaton" "ups" "5" "Nova AVR 625/1250" "USB" "usbhid-ups"
"Eaton" "ups" "5" "5E650iUSB" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "5E1100iUSB" "USB port" "usbhid-ups" # http://powerquality.eaton.com/5E1100iUSB.aspx?CX&GUID=8D85FE66-3102-427C-8F33-B8D56BBDD4D3
"Eaton" "ups" "4" "5E2200" "USB port" "nutdrv_qx"
"Eaton" "ups" "5" "5S" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "5SC" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "5P" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "9SX" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "EX 700/1000/1500 VA" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "EX 2200/3000/3000 XL VA" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "EX 1000 RT2U / 1500 RT2U" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "MX 5/8/10/15/20 kVA" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "5 PX" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "EX RT 1:1 7/11 kVA" "" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "EX RT 3:1 5/7/11 kVA" "" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "5SC" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "5P" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "9SX" "Serial port" "mge-shut or oldmge-shut"
"Eaton" "ups" "5" "9PX" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "9PX Split Phase 6/8/10 kVA" "USB port" "usbhid-ups"
"Eaton" "ups" "5" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut"
"Eaton" "ups" "5" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut"
"Eaton" "ups" "5" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "EX 700/1000/1500 VA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "EX 2200/3000/3000 XL VA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "EX 1000 RT2U / 1500 RT2U" "Serial port" "mge-shut"
"Eaton" "ups" "5" "MX 5/8/10/15/20 kVA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "5 PX" "Serial port" "mge-shut"
"Eaton" "ups" "5" "EX RT 1:1 7/11 kVA" "" "mge-shut"
"Eaton" "ups" "5" "EX RT 3:1 5/7/11 kVA" "" "mge-shut"
"Eaton" "ups" "5" "5SC" "Serial port" "mge-shut"
"Eaton" "ups" "5" "5P" "Serial port" "mge-shut"
"Eaton" "ups" "5" "9SX" "Serial port" "mge-shut"
"Eaton" "ups" "5" "9PX" "Serial port" "mge-shut"
"Eaton" "ups" "5" "9PX 2000 RT" "USB port" "mge-shut" # https://github.com/networkupstools/nut/issues/540
"Eaton" "ups" "5" "9PX Split Phase 6/8/10 kVA" "Serial port" "mge-shut"
"Eaton" "ups" "5" "9PX" "SNMP/Web card" "netxml-ups"
"Eaton" "ups" "5" "9PX Split Phase 6/8/10 kVA" "SNMP/Web card" "netxml-ups"
"Eaton" "ups" "5" "EX RT (XML/HTTP)" "NMC Transverse card (ref 66074)" "netxml-ups (experimental)"
"Eaton" "ups" "5" "EX RT (SNMP)" "NMC Transverse card (ref 66074)" "snmp-ups (experimental)"
"Eaton" "ups" "5" "E Series NV UPS 400-2000 VA" "" "blazer_usb"
@ -328,14 +384,21 @@
"Eaton" "ups" "5" "ConnectUPS X / BD / E Slot" "Network port" "snmp-ups"
"Eaton" "ups" "5" "Management Card Contact" "Config 3 - Cable 66033" "genericups upstype=7"
"Eaton" "ats" "5" "Eaton ATS16" "" "snmp-ups"
"Eaton" "ats" "5" "Eaton ATS30" "" "snmp-ups"
"Effekta" "ups" "2" "MI/MT/MH" "2502 cable" "blazer_ser"
"Effekta" "ups" "2" "RM2000MH" "" "blazer_ser"
"Electrys" "ups" "2" "UPS 2500" "" "nutdrv_qx or blazer_ser"
"Elsist" "ups" "2" "Nemo2.0 160" "USB" "blazer_usb" # http://www.naicon.com/company/wp-content/uploads/2017/05/Manual-NEMO2.0-Ver.02-Eng.pdf https://github.com/networkupstools/nut/issues/719
"Emerson" "pdu" "3" "PM3000 metered & switched" "" "snmp-ups"
"Energy Sistem" "ups" "2" "(various)" "" "blazer_ser"
"Energy Technologies" "ups" "2" "DPK1/1-3" "Serial" "blazer_ser" # https://www.tensy.ru/podderzhka/dokumentatsiya/ibp-serii-dpk/ https://github.com/networkupstools/nut/issues/762
"ETA" "ups" "1" "mini+UPS" "WinNT/Upsoft cable" "genericups upstype=7"
"ETA" "ups" "1" "mini+UPS PRO" "UPS Explorer cable" "etapro"
@ -351,6 +414,7 @@
"EVER" "ups" "2" "DUO II Pro series" "USB port" "blazer_usb"
"EVER" "ups" "2" "POWERLINE RT 1-3kVA series" "USB port" "blazer_usb"
"EVER" "ups" "2" "POWERLINE RT 6-10kVA series" "USB port" "blazer_usb"
"EVER" "ups" "4" "ECO Pro AVR CDS series" "USB port" "usbhid-ups"
"Exide" "ups" "1" "NetUPS SE" "" "genericups upstype=15"
"Exide" "ups" "4" "NetUPS SE 450/700/1000/1500" "" "upscode2"
@ -402,6 +466,9 @@
"Grafenthal" "ups" "2" "PR-3000-HS" "SNMP/Web Minislot card (ref 149G0006)" "snmp-ups" # http://grafenthal.de/produkte/usv/online/pr-hs-serie/pr-3000-hs/?L=3et8
"Greencell" "ups" "2" "Micropower 600" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1080
"Greencell" "ups" "2" "Micropower 600" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/1080
"Gtec" "ups" "2" "ZP120N-1K / ZP120N-1KS / ZP120N-2K / ZP120N-2KS / ZP120N-3K / ZP120N-3KS" "" "blazer_usb"
"Gtec" "ups" "2" "ZP120N-6K / ZP120N-6KS / ZP120N-10K-11 / ZP120N-10KS-11" "" "blazer_usb"
"Gtec" "ups" "2" "ZP120N-10K-31-00 / ZP120N-10K-31-07 / ZP120N-10K-31-09 / ZP120N-10K-31-99 / ZP120N-20K" "USB port" "blazer_usb"
@ -409,6 +476,8 @@
"Gtec" "ups" "2" "ZP120N-10K-31-00 / ZP120N-10K-31-07 / ZP120N-10K-31-09 / ZP120N-10K-31-99 / ZP120N-20K" "Serial port" "blazer_ser"
"Gtec" "ups" "2" "AP160N-1K / AP160LCD-1K-KS / AP160N-2K / AP160LCD-2K-KS / AP160N-3K / AP160LCD-3K-KS / AP160N-6K-PDU / AP160N-10K-PDU" "Serial port" "blazer_ser"
"Guardian" "ups" "2" "LCD 1500 AP (IGA1500LCD)" "Serial" "nutdrv_qx"
"HP" "ups" "1" "PowerTrust 2997A" "HP 5061-2575 cable" "apcsmart"
"HP" "ups" "3" "T750 G2" "Serial port" "bcmxcp"
"HP" "ups" "3" "T1000 G3" "Serial port" "bcmxcp"
@ -417,8 +486,8 @@
"HP" "ups" "4" "R3000 XR" "" "bcmxcp"
"HP" "ups" "4" "R5500 XR" "" "bcmxcp"
"HP" "ups" "3" "T500 / T750" "older models, USB port" "bcmxcp_usb"
"HP" "ups" "3" "R/T3000" "Serial port" "mge-shut or oldmge-shut"
"HP" "ups" "3" "R5000 / R7000" "Serial port" "mge-shut or oldmge-shut"
"HP" "ups" "3" "R/T3000" "Serial port" "mge-shut"
"HP" "ups" "3" "R5000 / R7000" "Serial port" "mge-shut"
"HP" "ups" "3" "T750 INTL" "" "usbhid-ups"
"HP" "ups" "3" "T1000 INTL" "" "usbhid-ups"
"HP" "ups" "3" "T1500 INTL" "" "usbhid-ups"
@ -432,8 +501,15 @@
"HP" "ups" "4" "Various (SNMP mode)" "HP UPS Management Module" "snmp-ups"
"HP" "pdu" "1" "HP3488 Switch/Control Unit" "" "powerman-pdu (experimental)"
"Huawei" "ups" "4" "UPS5000-E" "" "snmp-ups"
"HPE" "pdu" "5" "Various (SNMP mode)" "" "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
"Hunnox" "ups" "2" "HNX-850" "USB" "nutdrv_qx port=auto vendorid=0001 productid=0000 protocol=hunnox langid_fix=0x0409 novendor noscanlangid" # https://github.com/networkupstools/nut/pull/638
"IBM" "ups" "5" "Various" "USB port" "usbhid-ups"
"IBM" "ups" "5" "Various" "Serial port" "mge-shut"
"IBM" "pdu" "1" "Blade Center Management Module" "15 outlets" "powerman-pdu (experimental)"
"ICS" "pdu" "1" "8064 Ethernet Relay Interface" "16 outlets" "powerman-pdu (experimental)"
@ -461,10 +537,12 @@
"IPMI" "pdu" "1" "" "" "powerman-pdu (experimental)"
"Ippon" "ups" "2" "Back Basic 850 Euro" "USB" "blazer_usb (experimental)" # https://github.com/networkupstools/nut/issues/802
"Ippon" "ups" "2" "Back Power Pro 400/500/600/700/800" "" "blazer_ser"
"Ippon" "ups" "2" "Back Power Pro 400/500/600/700/800" "USB" "blazer_usb (experimental)"
"Ippon" "ups" "2" "Back Comfo Pro 600/800" "" "blazer_ser"
"Ippon" "ups" "2" "Back Comfo Pro 600/800" "USB" "blazer_usb (experimental)"
"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 Winner 750/1000/1500/2000/3000" "" "blazer_ser"
@ -482,6 +560,8 @@
"Kanji" "ups" "1" "800 VA" "USB" "nutdrv_atcl_usb"
"Kebo" "ups" "2" "1200D/D Series" "" "blazer_ser"
"Kebo" "ups" "2" "UPS-1000D (UPS-1000VA)" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/981
"Kebo" "ups" "2" "UPS-650VA" "USB" "megatec_usb"
"KOLFF" "ups" "2" "BLACK NOVA 1K/2K/3K/6K/10K/20K TOWER" "" "blazer_usb"
"KOLFF" "ups" "2" "BLACK NOVA 1K/2K/3K/6K/10K/20K XL TOWER" "" "blazer_usb"
@ -495,7 +575,43 @@
"LDLC" "ups" "2" "UPS-1200D" "" "blazer_usb langid_fix=0x4095"
"Legrand" "ups" "2" "Keor Multiplug" "" "nutdrv_qx"
"Legrand" "ups" "2" "Daker DK" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Daker DK" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Daker DK Plus" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Daker DK Plus" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Keor Line RT" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Keor Line RT" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Keor LP" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Keor Multiplug" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Keor S" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Keor S" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Keor PDU" "USB" "usbhid-ups"
"Legrand" "ups" "2" "Keor SP" "USB" "usbhid-ups"
"Legrand" "ups" "2" "Keor SPX" "USB" "nutdrv_qx"
"Legrand" "ups" "4" "Megaline 1250" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 2500" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 3750" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 5000" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 5000 /2" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 6250 /2" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 7500 /2" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 8750 /2" "Serial" "metasys"
"Legrand" "ups" "4" "Megaline 10000 /2" "Serial" "metasys"
"Legrand" "ups" "2" "Niky" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Niky" "USB" "nutdrv_qx"
"Legrand" "ups" "2" "Niky S" "Serial" "nutdrv_qx"
"Legrand" "ups" "2" "Niky S" "USB" "nutdrv_qx"
"Legrand" "ups" "4" "WHAD 800" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD 1000" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD 1250" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD 1500" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD 2000" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD 2500" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD CAB 1250" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD CAB 2500" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD HE 800" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD HE 1000" "Serial" "metasys"
"Legrand" "ups" "4" "WHAD HE 1500" "Serial" "metasys"
"Lestar" "ups" "2" "MD-800E" "" "blazer_ser"
@ -506,6 +622,8 @@
"Liebert" "ups" "1" "GXT2-3000RT230" "" "liebert-esp2 (experimental)"
"Liebert" "ups" "2" "PowerSure Personal XT" "USB" "usbhid-ups"
"Liebert" "ups" "2" "PowerSure PSA" "USB" "usbhid-ups"
"Liebert" "ups" "2" "PowerSure PSA 500" "USB" "usbhid-ups"
"Liebert" "ups" "2" "PowerSure PSA500MT3-230U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/601
"Liebert" "ups" "2" "PowerSure PSI 1440" "USB" "usbhid-ups" # http://www.emersonnetworkpower.com/en-US/Products/ACPower/Pages/LiebertPowerSurePSILineInteractiveUPS10003000VA.aspx
"LNXI" "pdu" "1" "Icebox" "10 outlets" "powerman-pdu (experimental)"
@ -520,48 +638,50 @@
"Mecer" "ups" "2" "ME-1000-WTU" "USB" "nutdrv_qx" # http://www.comx-computers.co.za/download/mecer/ME-1000-WTU.pdf
"Mecer" "ups" "2" "ME-2000" "" "blazer_ser"
"Meta System" "ups" "1" "HF Line" "1..4 boards" "metasys"
"Meta System" "ups" "1" "HF Line \/2" "5..8 boards" "metasys"
"Meta System" "ups" "1" "HF Millennium 810" "" "metasys"
"Meta System" "ups" "1" "HF Millennium 820" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 910" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 920" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 930" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 940" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 950" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 960" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 970" "" "metasys"
"Meta System" "ups" "1" "HF TOP Line 980" "" "metasys"
"Meta System" "ups" "1" "ECO Network 750" "" "metasys"
"Meta System" "ups" "1" "ECO Network 1000" "" "metasys"
"Meta System" "ups" "1" "ECO Network 1050" "" "metasys"
"Meta System" "ups" "1" "ECO Network 1500" "" "metasys"
"Meta System" "ups" "1" "ECO Network 1800" "" "metasys"
"Meta System" "ups" "1" "ECO Network 2000" "" "metasys"
"Meta System" "ups" "1" "ECO Network 2100" "" "metasys"
"Meta System" "ups" "1" "ECO Network 2500" "" "metasys"
"Meta System" "ups" "1" "ECO Network 3000" "" "metasys"
"Meta System" "ups" "1" "ECO 305" "" "metasys"
"Meta System" "ups" "1" "ECO 308" "" "metasys"
"Meta System" "ups" "1" "ECO 311" "" "metasys"
"Meta System" "ups" "1" "ECO 511" "" "metasys"
"Meta System" "ups" "1" "ECO 516" "" "metasys"
"Meta System" "ups" "1" "ECO 519" "" "metasys"
"Meta System" "ups" "1" "ECO 522" "" "metasys"
"Meta System" "ups" "1" "ally HF 800" "" "metasys"
"Meta System" "ups" "1" "ally HF 1000" "" "metasys"
"Meta System" "ups" "1" "ally HF 1250" "" "metasys"
"Meta System" "ups" "1" "ally HF 1600" "" "metasys"
"Meta System" "ups" "1" "ally HF 2000" "" "metasys"
"Meta System" "ups" "1" "ally HF 2500" "" "metasys"
"Meta System" "ups" "1" "Megaline 1250" "" "metasys"
"Meta System" "ups" "1" "Megaline 2500" "" "metasys"
"Meta System" "ups" "1" "Megaline 3750" "" "metasys"
"Meta System" "ups" "1" "Megaline 5000" "" "metasys"
"Meta System" "ups" "1" "Megaline 6250" "" "metasys"
"Meta System" "ups" "1" "Megaline 7500" "" "metasys"
"Meta System" "ups" "1" "Megaline 8750" "" "metasys"
"Meta System" "ups" "1" "Megaline 10000" "" "metasys"
"Meta System" "ups" "4" "HF Line" "1..4 boards" "metasys"
"Meta System" "ups" "4" "HF Line /2" "5..8 boards" "metasys"
"Meta System" "ups" "4" "HF Millennium 810" "" "metasys"
"Meta System" "ups" "4" "HF Millennium 820" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 910" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 920" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 930" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 940" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 950" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 960" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 970" "" "metasys"
"Meta System" "ups" "4" "HF TOP Line 980" "" "metasys"
"Meta System" "ups" "4" "ECO Network 750" "" "metasys"
"Meta System" "ups" "4" "ECO Network 1000" "" "metasys"
"Meta System" "ups" "4" "ECO Network 1050" "" "metasys"
"Meta System" "ups" "4" "ECO Network 1500" "" "metasys"
"Meta System" "ups" "4" "ECO Network 1800" "" "metasys"
"Meta System" "ups" "4" "ECO Network 2000" "" "metasys"
"Meta System" "ups" "4" "ECO Network 2100" "" "metasys"
"Meta System" "ups" "4" "ECO Network 2500" "" "metasys"
"Meta System" "ups" "4" "ECO Network 3000" "" "metasys"
"Meta System" "ups" "4" "ECO 305" "" "metasys"
"Meta System" "ups" "4" "ECO 308" "" "metasys"
"Meta System" "ups" "4" "ECO 311" "" "metasys"
"Meta System" "ups" "4" "ECO 511" "" "metasys"
"Meta System" "ups" "4" "ECO 516" "" "metasys"
"Meta System" "ups" "4" "ECO 519" "" "metasys"
"Meta System" "ups" "4" "ECO 522" "" "metasys"
"Meta System" "ups" "4" "ally HF 800" "" "metasys"
"Meta System" "ups" "4" "ally HF 1000" "" "metasys"
"Meta System" "ups" "4" "ally HF 1250" "" "metasys"
"Meta System" "ups" "4" "ally HF 1600" "" "metasys"
"Meta System" "ups" "4" "ally HF 2000" "" "metasys"
"Meta System" "ups" "4" "ally HF 2500" "" "metasys"
"Meta System" "ups" "4" "Megaline 1250" "" "metasys"
"Meta System" "ups" "4" "Megaline 2500" "" "metasys"
"Meta System" "ups" "4" "Megaline 3750" "" "metasys"
"Meta System" "ups" "4" "Megaline 5000" "" "metasys"
"Meta System" "ups" "4" "Megaline 6250" "" "metasys"
"Meta System" "ups" "4" "Megaline 7500" "" "metasys"
"Meta System" "ups" "4" "Megaline 8750" "" "metasys"
"Meta System" "ups" "4" "Megaline 10000" "" "metasys"
"Meta System" "ups" "4" "DHEA 1000" "Serial" "metasys"
"Meta System" "ups" "4" "DHEA 1500" "Serial" "metasys"
"MGE Office Protection Systems" "ups" "5" "Protection Center 500/675 VA" "USB" "usbhid-ups"
"MGE Office Protection Systems" "ups" "5" "Protection Station 500/650/800 VA" "USB" "usbhid-ups"
@ -572,15 +692,15 @@
"MGE Office Protection Systems" "ups" "5" "Pulsar 700/1000/1500 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "ups" "5" "Pulsar M 2200/3000 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "ups" "5" "Pulsar MX 5/8/10/15/20 kVA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "ups" "5" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar 700/1000/1500 VA" "Serial port" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar M 2200/3000 VA" "Serial port" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar MX 5/8/10/15/20 kVA" "Serial port" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT 1:1 7/11 kVA" "" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT 3:1 5/7/11 kVA" "" "mge-shut or oldmge-shut"
"MGE Office Protection Systems" "ups" "5" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar 700/1000/1500 VA" "Serial port" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar M 2200/3000 VA" "Serial port" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Pulsar MX 5/8/10/15/20 kVA" "Serial port" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT 1:1 7/11 kVA" "" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT 3:1 5/7/11 kVA" "" "mge-shut"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT (XML/HTTP)" "NMC Transverse card (ref 66074)" "netxml-ups (experimental)"
"MGE Office Protection Systems" "ups" "5" "Comet EX RT (SNMP)" "NMC Transverse card (ref 66074)" "snmp-ups (experimental)"
"MGE Office Protection Systems" "ups" "5" "various models (XML/HTTP mode)" "NMC Minislot (Ref 66102)" "netxml-ups (experimental)"
@ -628,45 +748,45 @@
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 4000 RT" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 5000 RT" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "ups" "5" "Comet / Galaxy (USB)" "USB Card (ref 66067)" "usbhid-ups"
"MGE UPS SYSTEMS" "ups" "5" "NOVA AVR 600 Serial" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "NOVA AVR 1100 Serial" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse USBS" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse S" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse Premium USBS" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse Premium S" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 600" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 750" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 1000" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 1500" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 600" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 850" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 1100" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 1500" "Serial cable" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar EXtreme C / EX RT" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Comet EX RT" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Comet EX RT 3:1" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Esprit" "" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 650" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 850" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 1150" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 1250" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 1550" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 1750" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 2000" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 2500" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 3000" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 2200" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 3000" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 3000 XL" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 700" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1000" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1500" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1000 RT2U" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1500 RT2U" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 4000 RT" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 5000 RT" "Serial port" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Evolution" "Serial port" "mge-shut or oldmge-shut or mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar EXtreme C" "" "mge-shut or oldmge-shut or mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "NOVA AVR 600 Serial" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "NOVA AVR 1100 Serial" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse USBS" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse S" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse Premium USBS" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Ellipse Premium S" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 600" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 750" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 1000" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse Office 1500" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 600" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 850" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 1100" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Ellipse MAX 1500" "Serial cable" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar EXtreme C / EX RT" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Comet EX RT" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Comet EX RT 3:1" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Esprit" "" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 650" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 850" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 1150" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 1250" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 1550" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 1750" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution 2000" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 2500" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Evolution S 3000" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 2200" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 3000" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar M 3000 XL" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 700" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1000" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1500" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1000 RT2U" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar 1500 RT2U" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 4000 RT" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar MX 5000 RT" "Serial port" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar Evolution" "Serial port" "mge-shut or mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar EXtreme C" "" "mge-shut or mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar ES+" "" "mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar ESV+" "" "mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar SV" "" "mge-utalk"
@ -678,7 +798,7 @@
"MGE UPS SYSTEMS" "ups" "5" "Pulsar EXtreme" "" "mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Comet EXtreme" "" "mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Comet / Galaxy (Serial)" "Utalk Serial Card (ref 66060)" "mge-utalk"
"MGE UPS SYSTEMS" "ups" "5" "Comet / Galaxy (Serial)" "HID COM Serial Card (ref 66066)" "mge-shut or oldmge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Comet / Galaxy (Serial)" "HID COM Serial Card (ref 66066)" "mge-shut"
"MGE UPS SYSTEMS" "ups" "5" "Pulsar / Comet / Galaxy (SNMP)" "SNMP/Web Transverse card (ref 66074)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "ups" "5" "various models (XML/HTTP mode)" "NMC Minislot (Ref 66102)" "netxml-ups (experimental)"
"MGE UPS SYSTEMS" "ups" "5" "various models (SNMP mode)" "NMC Minislot (Ref 66102)" "snmp-ups (experimental)"
@ -751,10 +871,14 @@
"Nitram" "ups" "1" "Elite 2002" "" "genericups upstype=16"
"Nitram" "ups" "1" "Elite 2005" "" "powerpanel"
"nJoy" "ups" "2" "Keen 600" "USB" "blazer_ser port=/dev/ttyUSB0" # https://www.njoy.ro/UPS/keen-600
"nJoy" "ups" "2" "Keen 600" "USB" "nutdrv_qx port=/dev/ttyUSB0" # https://www.njoy.ro/UPS/keen-600
"nJoy" "ups" "3" "Aten PRO 3000" "SNMP" "snmp-ups" # At least basic status is served; https://www.njoy.global/product/aten-pro-3000
"Novex" "ups" "1" "NUPS-650" "USB" "blazer_usb protocol=megatec" # http://komp.1k.by/periphery-ups/novex/Novex_NUPS_650-130052.html
"Numeric" "ups" "2" "3000 SW" "" "blazer_ser"
"Numeric" "ups" "2" "Digital 800 plus" "USB" "blazer_usb"
"Numeric" "ups" "2" "Digital 800 plus" "USB" "nutdrv_qx or blazer_usb"
"Oneac" "ups" "1" "ON400" "advanced interface" "oneac"
"Oneac" "ups" "1" "ON600" "advanced interface" "oneac"
@ -778,16 +902,24 @@
"Online" "ups" "2" "Zinto A" "" "blazer_usb"
"Online" "ups" "1" "Zinto D" "" "optiups"
"Online" "ups" "2" "Yunto YQ450" "" "blazer_usb"
"Online" "ups" "2" "Xanto S700" "/dev/ttyUSB0" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1279
"OnLite" "ups" "2" "AQUA" "50" "blazer_ser"
"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"
"Orvaldi Power Protection" "ups" "2" "various" "not 400 or 600" "blazer_ser"
"Orvaldi Power Protection" "ups" "2" "750 / 900SP" "" "blazer_usb"
"Phasak" "ups" "2" "400VA / 600VA" "" "blazer_ser"
"Phasak" "ups" "2" "9465 or P6N" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1187 => Voltronic-QS-Hex protocol detected
"PhoenixContact" "ups" "4" "QUINT-UPS/24DC" "2320461" "phoenixcontact_modbus" #https://www.phoenixcontact.com/online/portal/us?uri=pxc-oc-itemdetail:pid=2320461
"PiJuice" "ups" "5" "PiJuice HAT" "" "pijuice" # https://github.com/PiSupply/PiJuice/issues/124
"PiJuice" "ups" "5" "PiJuice Zero pHAT" "" "pijuice"
"Plexus" "ups" "2" "500VA" "USB" "blazer_usb"
"Plexus" "ups" "2" "1000VA Pro" "USB" "blazer_usb"
@ -812,6 +944,14 @@
"Powercom" "ups" "5" "(various)" "USB (2009 models, product id: 00a?)" "usbhid-ups (experimental)"
"Powercom" "ups" "5" "BNT-xxxAP" "USB (product id: 0004)" "usbhid-ups (experimental)"
"Powercom" "ups" "1" "BNT-xxxAP" "USB (product id: 0001)" "usbhid-ups (experimental)"
"Powercom" "ups" "3" "RPT-600AP" "USB" "usbhid-ups" # http://pcmups.com.tw/eA/html/product/show.php?num=226&root=13&kind=105&page=1&keyword= https://github.com/networkupstools/nut/issues/633
"Powercom" "ups" "3" "Raptor 2000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/633
"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" "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
"POWEREX" "ups" "2" "VI 1000 LED" "" "blazer_usb"
@ -839,6 +979,18 @@
"PowerWalker" "ups" "2" "Line-Interactive VI 850 LCD" "" "blazer_usb"
"PowerWalker" "ups" "2" "Online VFI 1000RT/1500RT/2000RT/3000RT/6000RT/10000RT LCD" "" "blazer_usb"
"PowerWalker" "ups" "2" "Line-Interactive VI 1000RT/1500RT/2000RT/3000RT LCD" "" "blazer_usb"
"PowerWalker" "ups" "2" "VFI 1000 CG PF1" "" "nutdrv_qx" # https://powerwalker.com/?page=product&item=10122108&lang=en
"PowerWalker" "ups" "2" "VFI 2000 TGS" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/560 and https://github.com/networkupstools/nut/pull/564
"PowerWalker" "ups" "2" "VI 650 SH" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/483
"PowerWalker" "ups" "2" "VI 650/850 SHL" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/646
"PowerWalker" "ups" "2" "VI 1200 SHL" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/1270
"PowerWalker" "ups" "2" "VI 2200 SHL" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/756
"PowerWalker" "ups" "2" "VI 1200 SH" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/646
"PowerWalker" "ups" "2" "VI 2200 SH" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/646
"PowerWalker" "ups" "2" "Basic VI 1000 SB" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/818
"PowerWalker" "ups" "2" "PR1500LCDRT2U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/818
"PowerWalker" "ups" "2" "VI 3000 SCL" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/971
"PowerWalker" "ups" "2" "VI 750T/HID" "USB" "usbhid-ups" # https://powerwalker.com/?page=select&cat=VI_THID&lang=en https://github.com/networkupstools/nut/issues/774
"Powerware" "ups" "4" "3110" "" "genericups upstype=7"
"Powerware" "ups" "4" "3115" "" "genericups upstype=11"
@ -868,6 +1020,7 @@
"Raritan" "pdu" "3" "Intelligent PDU - Dominion PX" "no report, but should be supported" "snmp-ups (experimental)"
"Raritan" "pdu" "3" "Metered PDU - Raritan PM" "no report, but should be supported" "snmp-ups (experimental)"
"Raritan" "pdu" "3" "Switched PDU - Raritan RPC" "no report, but should be supported" "snmp-ups (experimental)"
"Raritan" "pdu" "3" "Dominion PX2" "" "snmp-ups"
"REDi" "ups" "2" "Blazer 400VA / 600VA / 800VA" "" "blazer_ser"
@ -877,8 +1030,8 @@
"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" "5" "IDG 400/600/800/1200/1600" "" "riello_usb"
"Riello" "ups" "5" "IPG 600/800" "" "riello_usb"
"Riello" "ups" "4" "IDG 400/600/800/1200/1600" "" "riello_usb"
"Riello" "ups" "4" "IPG 600/800" "" "riello_usb"
"Riello" "ups" "5" "WPG 400/600/800" "" "riello_usb"
"Riello" "ups" "5" "NPW 600/800/1000/1500/2000" "" "riello_usb"
"Riello" "ups" "5" "NDG 800/1000/1500/2000" "" "riello_usb"
@ -918,10 +1071,37 @@
"Rucelf" "ups" "2" "Rucelf UPOII-3000-96-EL" "" "blazer_ser" # http://www.rucelf.ua/en/catalog/upoii-3000-96-el/
"Salicru" "ups" "2" "SPS ONE 700VA" "USB" "blazer_usb"
"Salicru" "ups" "2" "SPS ONE 2000VA" "USB" "nutdrv_qx" # https://www.salicru.com/en/ups/sps-one.html https://github.com/networkupstools/nut/issues/554
"Salicru" "ups" "2" "SPS 650/850 HOME" "usb" "usbhid-ups (experimental)"
"Salicru" "ups" "2" "SLC TWIN PRO2" "usb" "usbhid-ups (experimental)" # https://github.com/networkupstools/nut/issues/450
"Salicru" "ups" "2" "SLC-1500-TWIN PRO3" "usb" "usbhid-ups (experimental)" # https://github.com/networkupstools/nut/issues/1142
"Salicru" "ups" "2" "SLC TWINPRO3" "usb" "usbhid-ups (experimental)"
"Salicru" "ups" "2" "SLC TWIN RT3" "usb" "usbhid-ups (experimental)"
"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
"Siemens" "ups" "4" "SITOP UPS500" "serial" "nutdrv_siemens_sitop (experimental, untested)"
"Siemens" "ups" "4" "SITOP UPS500" "USB" "nutdrv_siemens_sitop (experimental)"
"SmartLabs" "pdu" "1" "2412S Power Line Modem" "for X10/Insteon" "powerman-pdu (experimental)"
"SMS (Brazil)" "ups" "2" "Manager III" "" "blazer_ser"
"SNR" "ups" "2" "SNR-UPS-LID-600" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-600-XPS" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-600-LED-C13" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-600-LED-C13-PRO" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-800" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-800-LED-С13" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-1000-XPS" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-1200" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-1500" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-2000" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-2000-XPS" "" "nutdrv_qx"
"SNR" "ups" "2" "SNR-UPS-LID-3000-XPS" "" "nutdrv_qx"
"SOLA" "ups" "1" "305" "cable INT-0025C" "genericups upstype=7"
"SOLA" "ups" "1" "325" "" "blazer_ser or bestups"
"SOLA" "ups" "1" "520" "" "blazer_ser or bestups"
@ -962,11 +1142,13 @@
"Sweex" "ups" "2" "INTELLIGENT UPS 1500VA P220" "USB" "blazer_usb (USB ID 0665:5161)" # http://www.sweex.com/en/notebook-pc-accessoires/ups/PP220/
"Syndome" "ups" "2" "Era 500VA" "USB" "blazer_usb"
"Syndome" "ups" "2" "Atom LCD-1000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/483
"Sysgration" "ups" "2" "UPGUARDS Pro650" "" "blazer_ser"
"Tecnoware" "ups" "2" "Easy Power 1200" "" "blazer_ser"
"Tecnoware" "ups" "2" "UPS ERA LCD 0.65" "" "blazer_usb langid_fix=0x409"
"Tecnoware" "ups" "2" "UPS ERA LCD 0.65" "USB" "blazer_usb langid_fix=0x409"
"Tecnoware" "ups" "2" "UPS ERA PLUS 1100" "USB" "blazer_usb" # https://www.tecnoware.com/Prodotti/FGCERAPL1100/ups-era-plus-1100.aspx https://github.com/networkupstools/nut/issues/747
"Tripp Lite" "ups" "1" "(various)" "Lan 2.2 interface - black 73-0844 cable" "genericups upstype=5"
"Tripp Lite" "ups" "2" "1500 LCD" "USB" "usbhid-ups"
@ -1068,7 +1250,8 @@
"Tripp Lite" "ups" "3" "SMX3000RT2UTAA" "USB (protocol 3015)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=4396
"Tripp Lite" "ups" "3" "SMX3000XLRT2U" "USB (protocol 3015)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtSeriesID=933&txtModelID=2694
"Tripp Lite" "ups" "3" "SMX3000XLRT2UA" "USB (protocol 3015)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=5658
"Tripp Lite" "ups" "3" "SMX500RT1U" "USB (protocol 3005)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=2691
"Tripp Lite" "ups" "3" "SMX500RT1U" "USB (older; product ID 0001, protocol 3005)" "tripplite_usb" # https://www.tripplite.com/support/product/part-number/SMX500RT1U https://github.com/networkupstools/nut/pull/584
"Tripp Lite" "ups" "3" "SMX500RT1U" "USB (newer; protocol/product ID 3005)" "usbhid-ups" # https://www.tripplite.com/support/product/part-number/SMX500RT1U
"Tripp Lite" "ups" "3" "SMX750SLT" "USB (protocol 3014)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=3021
"Tripp Lite" "ups" "3" "SU750RTXL2U" "USB (protocol 4001)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=3194
"Tripp Lite" "ups" "3" "SU750RTXLCD2U" "USB (protocol 4004)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=5070
@ -1119,6 +1302,8 @@
"UPSonic" "ups" "2" "PrOffice 650" "USB" "blazer_usb"
"UPSonic" "ups" "2" "DS-800" "USB" "blazer_usb"
"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
"Various" "ups" "4" "(various)" "SEC protocol" "gamatronic"
"Various" "ups" "1" "(various)" "Generic RUPS model" "genericups upstype=4"
"Various" "ups" "1" "(various)" "Generic RUPS 2000 (Megatec M2501 cable)" "genericups upstype=21"
@ -1149,6 +1334,8 @@
"Voltronic Power" "ups" "2" "Frigate TX 1KVA" "USB" "nutdrv_qx"
"Voltronic Power" "ups" "2" "Galleon 1KVA" "Serial" "nutdrv_qx"
"Voltronic Power" "ups" "2" "Galleon 1KVA" "USB" "nutdrv_qx"
"Voltronic Power" "ups" "2" "Galleon X9-RT LCD-1-3K" "USB" "blazer_usb" # https://github.com/networkupstools/nut/issues/1251
"Voltronic Power" "ups" "2" "Galleon X9-RT LCD-1-3K" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/1251
"Voltronic Power" "ups" "2" "Imperial 1KVA" "Serial" "nutdrv_qx"
"Voltronic Power" "ups" "2" "Imperial 1KVA" "USB" "nutdrv_qx"
"Voltronic Power" "ups" "2" "Prosine 800" "Serial" "nutdrv_qx"

View file

@ -5,3 +5,7 @@ if WITH_CGI
nodist_html_DATA = header.html
endif
EXTRA_DIST = README
MAINTAINERCLEANFILES = Makefile.in .dirstamp
# Generated by configure script:
DISTCLEANFILES = header.html

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -15,7 +15,17 @@
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -80,19 +90,24 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = data/html
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/header.html.in $(am__dist_html_DATA_DIST) README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -101,11 +116,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_html_DATA_DIST) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = header.html
@ -160,6 +182,8 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(htmldir)" "$(DESTDIR)$(htmldir)"
DATA = $(dist_html_DATA) $(nodist_html_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/header.html.in \
README
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A2X = @A2X@
ACLOCAL = @ACLOCAL@
@ -168,6 +192,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -178,6 +203,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -191,6 +217,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -203,6 +230,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -220,6 +248,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -230,21 +260,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -264,6 +302,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -277,6 +318,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -294,6 +336,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -307,6 +350,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -332,12 +378,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -353,6 +401,9 @@ udevdir = @udevdir@
@WITH_CGI_TRUE@dist_html_DATA = index.html bottom.html nut-banner.png
@WITH_CGI_TRUE@nodist_html_DATA = header.html
EXTRA_DIST = README
MAINTAINERCLEANFILES = Makefile.in .dirstamp
# Generated by configure script:
DISTCLEANFILES = header.html
all: all-am
.SUFFIXES:
@ -368,14 +419,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu data/html/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu data/html/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -443,7 +493,10 @@ ctags CTAGS:
cscope cscopelist:
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -506,10 +559,12 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
@ -592,6 +647,8 @@ uninstall-am: uninstall-dist_htmlDATA uninstall-nodist_htmlDATA
tags-am uninstall uninstall-am uninstall-dist_htmlDATA \
uninstall-nodist_htmlDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

7
debian/changelog vendored
View file

@ -1,3 +1,10 @@
nut (2.8.0-1) unstable; urgency=medium
[ lagertonne ]
* new upstream 2.8.0
-- lagertonne <mail@lagertonne.de> Wed, 29 Jun 2022 13:12:45 +0000
nut (2.7.4-14) unstable; urgency=medium
[ Jeremy Sowden ]

View file

@ -1,34 +0,0 @@
debian/tmp/usr/share/man/man3/libnutclient.3
debian/tmp/usr/share/man/man3/libnutclient_commands.3
debian/tmp/usr/share/man/man3/libnutclient_devices.3
debian/tmp/usr/share/man/man3/libnutclient_general.3
debian/tmp/usr/share/man/man3/libnutclient_misc.3
debian/tmp/usr/share/man/man3/libnutclient_tcp.3
debian/tmp/usr/share/man/man3/libnutclient_variables.3
debian/tmp/usr/share/man/man3/nutclient_authenticate.3
debian/tmp/usr/share/man/man3/nutclient_destroy.3
debian/tmp/usr/share/man/man3/nutclient_device_forced_shutdown.3
debian/tmp/usr/share/man/man3/nutclient_device_login.3
debian/tmp/usr/share/man/man3/nutclient_device_master.3
debian/tmp/usr/share/man/man3/nutclient_execute_device_command.3
debian/tmp/usr/share/man/man3/nutclient_get_device_command_description.3
debian/tmp/usr/share/man/man3/nutclient_get_device_commands.3
debian/tmp/usr/share/man/man3/nutclient_get_device_description.3
debian/tmp/usr/share/man/man3/nutclient_get_device_num_logins.3
debian/tmp/usr/share/man/man3/nutclient_get_device_rw_variables.3
debian/tmp/usr/share/man/man3/nutclient_get_device_variable_description.3
debian/tmp/usr/share/man/man3/nutclient_get_device_variable_values.3
debian/tmp/usr/share/man/man3/nutclient_get_device_variables.3
debian/tmp/usr/share/man/man3/nutclient_get_devices.3
debian/tmp/usr/share/man/man3/nutclient_has_device.3
debian/tmp/usr/share/man/man3/nutclient_has_device_command.3
debian/tmp/usr/share/man/man3/nutclient_has_device_variable.3
debian/tmp/usr/share/man/man3/nutclient_logout.3
debian/tmp/usr/share/man/man3/nutclient_set_device_variable_value.3
debian/tmp/usr/share/man/man3/nutclient_set_device_variable_values.3
debian/tmp/usr/share/man/man3/nutclient_tcp_create_client.3
debian/tmp/usr/share/man/man3/nutclient_tcp_disconnect.3
debian/tmp/usr/share/man/man3/nutclient_tcp_get_timeout.3
debian/tmp/usr/share/man/man3/nutclient_tcp_is_connected.3
debian/tmp/usr/share/man/man3/nutclient_tcp_reconnect.3
debian/tmp/usr/share/man/man3/nutclient_tcp_set_timeout.3

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man3/nutscan*.3

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man3/upscli*.3

View file

@ -1,6 +0,0 @@
debian/tmp/usr/share/man/man5/hosts.conf.5
debian/tmp/usr/share/man/man5/upsset.conf.5
debian/tmp/usr/share/man/man5/upsstats.html.5
debian/tmp/usr/share/man/man8/upsimage.cgi.8
debian/tmp/usr/share/man/man8/upsset.cgi.8
debian/tmp/usr/share/man/man8/upsstats.cgi.8

View file

@ -1,9 +0,0 @@
debian/tmp/usr/share/man/man5/nut.conf.5
debian/tmp/usr/share/man/man5/upsmon.conf.5
debian/tmp/usr/share/man/man5/upssched.conf.5
debian/tmp/usr/share/man/man8/upsc.8
debian/tmp/usr/share/man/man8/upscmd.8
debian/tmp/usr/share/man/man8/upslog.8
debian/tmp/usr/share/man/man8/upsmon.8
debian/tmp/usr/share/man/man8/upsrw.8
debian/tmp/usr/share/man/man8/upssched.8

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man8/nut-ipmipsu.8

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man8/powerman-pdu.8

View file

@ -36,7 +36,6 @@ debian/tmp/lib/nut/mge-utalk
debian/tmp/lib/nut/microdowell
debian/tmp/lib/nut/nutdrv_atcl_usb
debian/tmp/lib/nut/nutdrv_qx
debian/tmp/lib/nut/oldmge-shut
debian/tmp/lib/nut/oneac
debian/tmp/lib/nut/optiups
debian/tmp/lib/nut/powercom
@ -55,7 +54,10 @@ debian/tmp/lib/nut/upsd
debian/tmp/lib/nut/usbhid-ups
debian/tmp/lib/nut/victronups
debian/tmp/lib/systemd/system-shutdown/nutshutdown
debian/tmp/lib/systemd/system/nut-driver.service
debian/tmp/lib/systemd/system/nut-driver\@.service
debian/tmp/lib/systemd/system/nut-driver.target
debian/tmp/lib/systemd/system/nut-driver-enumerator.service
debian/tmp/lib/systemd/system/nut-driver-enumerator.path
debian/tmp/lib/systemd/system/nut-server.service
debian/tmp/sbin/upsd
debian/tmp/sbin/upsdrvctl

View file

@ -1,54 +0,0 @@
debian/tmp/usr/share/man/man5/ups.conf.5
debian/tmp/usr/share/man/man5/upsd.conf.5
debian/tmp/usr/share/man/man5/upsd.users.5
debian/tmp/usr/share/man/man8/al175.8
debian/tmp/usr/share/man/man8/apcsmart-old.8
debian/tmp/usr/share/man/man8/apcsmart.8
debian/tmp/usr/share/man/man8/apcupsd-ups.8
debian/tmp/usr/share/man/man8/bcmxcp.8
debian/tmp/usr/share/man/man8/bcmxcp_usb.8
debian/tmp/usr/share/man/man8/belkin.8
debian/tmp/usr/share/man/man8/belkinunv.8
debian/tmp/usr/share/man/man8/bestfcom.8
debian/tmp/usr/share/man/man8/bestfortress.8
debian/tmp/usr/share/man/man8/bestuferrups.8
debian/tmp/usr/share/man/man8/bestups.8
debian/tmp/usr/share/man/man8/blazer_ser.8
debian/tmp/usr/share/man/man8/blazer_usb.8
debian/tmp/usr/share/man/man8/clone.8
debian/tmp/usr/share/man/man8/dummy-ups.8
debian/tmp/usr/share/man/man8/etapro.8
debian/tmp/usr/share/man/man8/everups.8
debian/tmp/usr/share/man/man8/gamatronic.8
debian/tmp/usr/share/man/man8/genericups.8
debian/tmp/usr/share/man/man8/isbmex.8
debian/tmp/usr/share/man/man8/ivtscd.8
debian/tmp/usr/share/man/man8/liebert-esp2.8
debian/tmp/usr/share/man/man8/liebert.8
debian/tmp/usr/share/man/man8/masterguard.8
debian/tmp/usr/share/man/man8/metasys.8
debian/tmp/usr/share/man/man8/mge-shut.8
debian/tmp/usr/share/man/man8/mge-utalk.8
debian/tmp/usr/share/man/man8/microdowell.8
debian/tmp/usr/share/man/man8/nut-scanner.8
debian/tmp/usr/share/man/man8/nutdrv_atcl_usb.8
debian/tmp/usr/share/man/man8/nutdrv_qx.8
debian/tmp/usr/share/man/man8/nutupsdrv.8
debian/tmp/usr/share/man/man8/oneac.8
debian/tmp/usr/share/man/man8/optiups.8
debian/tmp/usr/share/man/man8/powercom.8
debian/tmp/usr/share/man/man8/powerpanel.8
debian/tmp/usr/share/man/man8/rhino.8
debian/tmp/usr/share/man/man8/richcomm_usb.8
debian/tmp/usr/share/man/man8/riello_ser.8
debian/tmp/usr/share/man/man8/riello_usb.8
debian/tmp/usr/share/man/man8/safenet.8
debian/tmp/usr/share/man/man8/solis.8
debian/tmp/usr/share/man/man8/tripplite.8
debian/tmp/usr/share/man/man8/tripplite_usb.8
debian/tmp/usr/share/man/man8/tripplitesu.8
debian/tmp/usr/share/man/man8/upscode2.8
debian/tmp/usr/share/man/man8/upsd.8
debian/tmp/usr/share/man/man8/upsdrvctl.8
debian/tmp/usr/share/man/man8/usbhid-ups.8
debian/tmp/usr/share/man/man8/victronups.8

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man8/snmp-ups.8

View file

@ -1 +0,0 @@
debian/tmp/usr/share/man/man8/netxml-ups.8

2
debian/rules vendored
View file

@ -103,7 +103,7 @@ ifeq ($(filter nodoc,$(DEB_BUILD_PROFILES)),)
mkdir -p $(CURDIR)/debian/tmp/usr/share/doc/nut-doc/pdf
mkdir -p $(CURDIR)/debian/tmp/usr/share/doc/nut-doc/html
cp $(CURDIR)/docs/*.pdf $(CURDIR)/debian/tmp/usr/share/doc/nut-doc/pdf
cp $(CURDIR)/docs/FAQ.html $(CURDIR)/debian/tmp/usr/share/doc/nut-doc/html
cp $(CURDIR)/docs/FAQ.txt $(CURDIR)/debian/tmp/usr/share/doc/nut-doc/html
for f in $(CURDIR)/docs/*.chunked/; do \
nf=`basename $${f} | sed 's/\(.*\)\.chunked/\1/'`; \

10
depcomp
View file

@ -1,9 +1,9 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# 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
@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -783,9 +783,9 @@ exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -4,8 +4,8 @@ NUT Frequently Asked Questions
endif::external_title[]
== I just upgraded, and ...
You have read link:UPGRADING[UPGRADING] in the base directory of the distribution,
right?
You have read link:UPGRADING[UPGRADING] in the base directory of the
distribution, right?
If not, go read it now, then come back to this file if your
question wasn't answered in there.
@ -88,16 +88,16 @@ Refer to the upsd(8) and upsd.conf(5) manpages for more information.
== I get a 'not listening on...' error from upsd.
Verify your LISTEN directive. It should be one of the valid IP addresses for
the computer running upsd (or 0.0.0.0, which is INADDR_ANY), not an address for
a client.
Verify your LISTEN directive. It should be one of the valid IP addresses
for the computer running `upsd` (or `0.0.0.0`, which is `INADDR_ANY`), not
an address for a client.
The LISTEN directive lets you pick which interface upsd listens on. If you are
trying to limit the clients which can connect to upsd, you either need to use
tcp-wrappers or kernel firewall rules.
The LISTEN directive lets you pick which interface `upsd` listens on.
If you are trying to limit the clients which can connect to `upsd`,
you either need to use tcp-wrappers or kernel firewall rules.
This isn't a NUT-specific limitation - it applies equally to your web server or
mailer daemon.
This isn't a NUT-specific limitation -- it applies equally to your web server
or mailer daemon.
== Which UPS should I buy?
@ -118,7 +118,7 @@ The Back-UPS type in the genericups driver works but then I don't get to use
all the nifty features in there. Why doesn't the right driver work?
The problem lies in your choice of cable. APC's grey cables
generally only do "dumb" signalling - very basic yes/no info about
generally only do "dumb" signalling -- very basic yes/no info about
the battery and line status. While that is sufficient to detect a
low battery condition while on battery, you miss out on all the
goodies that you paid for.
@ -138,9 +138,10 @@ If your grey cable isn't the 940-0095B, the solution is to dump that
cable and find one that supports APC's "smart" signalling. Typically
these come with the UPS and are black. If your smart cable has
wandered off, one can be built rather easily with some connectors and
cable - there's no fancy wiring or resistors.
cable -- there's no fancy wiring or resistors.
See this URL for a handy diagram: http://www.networkupstools.org/cables/940-0024C.jpg
See this URL for a handy diagram:
http://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
@ -176,8 +177,8 @@ Besides, if upsmon were rolled into upsd, upsd would get even
bigger than it is now. You'd have one less process, but the
RAM consumption would be pretty close to now.
See the "Data Room" section in docs/config-notes.txt for more configuration
ideas and explanations.
See the "Data Room" section in link:docs/config-notes.txt[] for
more configuration ideas and explanations.
*Answer 2*
@ -255,7 +256,7 @@ what's going on with the UPS.
Note: some drivers occasionally need more time to update than the
default value of MAXAGE (in upsd.conf) allows. As a result, they
are temporarily marked stale even though everything is fine. This
can happen with MGE Ellipse equipment - see the mge-shut or usbhid-ups man
can happen with MGE Ellipse equipment -- see the mge-shut or usbhid-ups man
pages. In such cases, you can raise the value of MAXAGE to avoid these
warnings; try a value like 25 or 30.
@ -272,6 +273,12 @@ Note: if you jumped in with both feet and didn't follow the INSTALL.nut
document, you probably started upsd by itself. You have to run
'upsdrvctl start' to start the drivers after configuring ups.conf.
On operating systems with a supported service management framework,
you might wrap your NUT drivers into individual services instances
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).
== Why don't the pathnames in your documentation match the package I installed?
Each distribution has conventions for where specific file types should be
@ -298,11 +305,14 @@ that point. You *want* the system to die without reaching the
part where the kernel tells it to shut down. A possible script
might look like this:
------
# other shutdown stuff here (mount -o remount,ro ...)
# `upsmon -K` if available on still mounted filesystems
# at this point is more portable than the `test` below
if (test -f /etc/killpower)
then
/usr/local/ups/sbin/upsdrvctl shutdown
/sbin/upsdrvctl shutdown
sleep 600 # this should never return
@ -311,6 +321,7 @@ might look like this:
fi
halt -p
------
The other solution is to change your BIOS setting to "always power
on" instead of "last state", assuming that's possible.
@ -324,7 +335,7 @@ things depending on what's supported:
- Set a jumper on the motherboard that means "return after outage"
- Set something in the BIOS that says "power up after power failure"
- Try using something (like a capacitor) across the power button
to "push" it for you - this might not work if it needs a delay
to "push" it for you -- this might not work if it needs a delay
- Hack the cable between the power supply and the motherboard to fool
it into powering up whenever line power is present
- Teach a monkey to watch the machine and press the power button
@ -342,14 +353,15 @@ cat some magic characters at /dev/adb to enable "server mode".
This would instruct the system to reboot while unattended.
From Usenet post <6boftzxz51.fsf@ecc-office.sp.cs.cmu.edu>:
------
# Send packet over the ADB bus to the PowerMac CUDA chip
# telling it to reboot automatically when power is restored
# after a power failure.
cat /etc/local/autoboot.adb > /dev/adb
autoboot.adb contains these three bytes (in hex): 01 13 01
# autoboot.adb contains these three bytes (in hex): 01 13 01
------
Later PowerPC Macs with a PMU and the appropriate kernel driver can achieve the
same effect with the following command:
@ -404,7 +416,7 @@ For my development system this yields the following /dev entries:
- Switch to root, then start the drivers:
# /usr/local/ups/sbin/upsdrvctl -u nutdev start
# upsdrvctl -u nutdev start
- The listing for /var/state/ups then looks like this:
@ -428,14 +440,14 @@ make the files owned by root.nut, with mode 0640.
Once the config files are ready, start upsd:
# /usr/local/ups/sbin/upsd -u nutsrv
# upsd -u nutsrv
Check your syslog to be sure everything's happy, then be sure to
update your startup scripts so it uses this procedure on your next
boot.
If you like this, you'll probably also find the chroot process to
be useful and interesting. See security.txt for more details.
be useful and interesting. See link:security.txt[] for more details.
== What's the point of that 'security domains' concept above?
@ -445,12 +457,12 @@ to that one user account. Direct access to the serial device is
not possible, since that is owned by another user.
There is also the possibility of running the drivers and upsd in a
chroot jail. See the chroot.txt provided in the source
distribution for an example implementation.
chroot jail. See the chroot option in link:security.txt[], `upsd`
and driver documentation.
Why give would-be vandals any sort of help?
Put it this way - I *wrote* good chunks of this stuff, and I still
Put it this way -- I *wrote* good chunks of this stuff, and I still
run the programs this way locally. You should definitely consider
using this technique.
@ -458,8 +470,8 @@ using this technique.
You probably don't want to do this, since it doesn't maximize your
runtime on battery. Assuming you have a good reason for it (see
the next entry), then look at scheduling.txt or the upssched(8) man
page for some ideas.
the next entry), then look at link:scheduling.txt[] or the
linkman:upssched[8] man page for some ideas.
/////////////////////////////////////////////////////////////////
TODO: figure out how to link to the upssched man page above.
@ -487,10 +499,10 @@ with no visible interruption in service.
If you purposely shut down early, you guarantee an interruption in
service by bringing down the box.
See upssched.txt for information on how you can shutdown early if
See link:upssched.txt[] for information on how you can shutdown early if
this is what you really want to do.
== The CGI programs report 'access to that host is not authorized' - what's going on?
== The CGI programs report 'access to that host is not authorized' -- what's going on?
Those programs need to see a host in your hosts.conf before they
will attempt communications. This keeps people from feeding it
@ -526,7 +538,7 @@ Either find the pid of the background process and send it a SIGHUP,
or just start it again with '-c reload'.
If you send the signals yourself instead of using -c, be sure you
hit the right process. There are usually two upsmons, and 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.
@ -537,17 +549,42 @@ There are several driver to support USB models.
- usbhid-ups supports various manufacturers complying to the HID Power Device Class (PDC) standard,
- tripplite_usb supports various older Tripp-Lite units (with USB ProductID 0001)
- bcmxcp_usb supports various Powerware units,
- nutdrv_qx and blazer_usb support various manufacturers that use the Megatec / Q1 protocol.
- blazer_usb supports various manufacturers that use the Megatec / Q1 protocol.
- nutdrv_qx supports various manufacturers that use the Megatec / Q* protocol
family. This is the driver slated to receive all further development in this
area, it was specially designed to support many more sub-drivers and has
added a lot over time, so please do try it first nowadays.
Refer to the 'driver-name' (8) manpage for more information.
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
== My USB UPS has a bogus Vendor ID 0x0001 and Product ID 0x0000, what driver supports it?
Unfortunately, many devices are made without registering as a Vendor with
the corresponding standards body, and use generic USB chips for interfacing
with a computer (roughly similar to using a network interface card with a
random MAC address and PCI ID, and thus poorly identifiable device specifics
needed to automatically load some certain driver). Often they also lack a
unique serial number field, so monitoring several devices is problematic.
One frequent case is with devices identifying as "Fry's Electronics" and/or
"MEC0003", if those data are served at all, or plain "0001/0000" in ID field.
In some cases they are accompanied by "UPSmart" software with a "MEGA(USB)"
connection option that works for Windows users.
Your best bet is to search for community discussions of issues on NUT GitHub
at https://github.com/networkupstools/nut/issues?q=is%3Aissue and try options
there. Devices with these chips were known to connect with drivers for such
unrelated protocols as Megatec Q* (different sub-drivers, often `fabula` or
`hunnox`), ATCL, or USB-HID.
== My USB UPS is supported but doesn't work!
On Linux, udev rules are provided to set the correct permissions on device file.
This allows the NUT driver to communicate with the UPS, through this device file.
On Linux, udev rules are provided to set the correct permissions on device
file. This allows the NUT driver to communicate with the UPS, through this
device file.
However, the driver may still fail to start and support the device, with a
message like:
@ -567,7 +604,7 @@ Instead of unplugging, you might also be able to run `udevadm trigger
There was a mistake in the naming of the NUT udev rules file which resulted in
the rules being overridden by another udev configuration file. While this has
been fixed in the Git master branch, your distribution may still be affected.
Details are available in the following Github issue:
Details are available in the following GitHub issue:
https://github.com/networkupstools/nut/issues/140
== Why do you not use the Linux kernel HID driver when communicating with USB UPSes?
@ -596,6 +633,79 @@ There is a rudimentary locking mechanism in NUT, but there is a chance that the
packages might not use the same directory as the NUT default, and the conflict
will be reported by the kernel.
== Why does my (Eaton 5E) USB UPS on Linux connect but quickly disconnects soon?
This issue was extensively investigated by NUT community members in
https://github.com/networkupstools/nut/issues/630 and resulted in a
chain of distribution bugs logged such as
https://bugzilla.redhat.com/show_bug.cgi?id=1715504
The gist of it is that some versions of Linux kernel used an "USB HID quirk"
for certain devices, see Linux kernel source `drivers/hid/hid-quirks.c` file,
including MGE/Eaton vendor ID (0x0463) based on an older device a contributor
had issues with. Firmware in newer devices no longer had the bug which needed
the "quirk" and misbehaved when it was enabled. While newer (and much older)
Linux kernels should not have the problem, with the quirk removed according
to https://lkml.org/lkml/2018/11/26/580 having the issue in the field really
depends on the combination of Linux kernel and device firmware that meet.
Either way, it seems that problematic combinations preclude Linux from seeing
the device as a `hid-generic` first, to hand it over to a NUT driver.
This quirk can be tuned with a kernel boot parameter (via GRUB etc.):
usbhid.quirks=0x0463:0xffff:0x08
to re-enable the NOGET quirk.
For context, according to https://bugzilla.redhat.com/show_bug.cgi?id=1875532
the symptoms for the problem look like this:
# Plug in the UPS and observe the dmesg logs,
# the following continuously appears:
[ 93.568082] usb 1-6: new full-speed USB device number 9 using xhci_hcd
[ 94.311469] usb 1-6: New USB device found, idVendor=0463, idProduct=ffff, bcdDevice= 0.01
[ 94.311475] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 94.311483] usb 1-6: Product: 5E
[ 94.311486] usb 1-6: Manufacturer: EATON
[ 96.269989] hid-generic 0003:0463:FFFF.000A: hiddev96,hidraw2: USB HID v1.10 Device [EATON 5E] on usb-0000:00:14.0-6/input0
[ 107.369425] hid-generic 0003:0463:FFFF.000A: usb_submit_urb(ctrl) failed: -1
[ 107.369469] hid-generic 0003:0463:FFFF.000A: timeout initializing reports
[ 112.828826] usb 1-6: USB disconnect, device number 9
[ 113.284452] usb 1-6: new full-speed USB device number 10 using xhci_hcd
[ 114.027693] usb 1-6: New USB device found, idVendor=0463, idProduct=ffff, bcdDevice= 0.01
[ 114.027698] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 114.027701] usb 1-6: Product: 5E
[ 114.027704] usb 1-6: Manufacturer: EATON
[ 115.984222] hid-generic 0003:0463:FFFF.000B: hiddev96,hidraw2: USB HID v1.10 Device [EATON 5E] on usb-0000:00:14.0-6/input0
[ 126.825756] hid-generic 0003:0463:FFFF.000B: usb_submit_urb(ctrl) failed: -1
[ 126.825775] hid-generic 0003:0463:FFFF.000B: timeout initializing reports
[ 132.527809] usb 1-6: USB disconnect, device number 10
A similar report on the driver side may look like:
usbhid-ups[4554]: libusb_get_report: Input/output error
upsd[4591]: Data for UPS [eaton] is stale - check driver
usbhid-ups[4554]: Can't claim USB device [0463:ffff]: No such file or directory
upsd[4591]: Can't connect to UPS [eaton] (usbhid-ups-eaton): No such file or directory
upsmon[5148]: Poll UPS [eaton@localhost] failed - Driver not connected
upsmon[5148]: Communications with UPS eaton@localhost lost
Other similar looking issues may include improper setup of udev, upower
and similar frameworks to hand over the device from the OS to a driver
daemon; competition with other software probing USB devices (ModemManager
was mentioned in this context), including running several copies of the
NUT drivers trying to use same port (e.g. one started by services and
another manually as you tried to debug the problems).
Software quirks aside, please do test with a different USB cable and/or port
on the computer. These were known to cause grief beyond what can be fixed
with a few key words ;)
Finally, sometimes the issue is on the OS side (and/or USB chipset), to
the point that the USB driver can not be unloaded and re-attached until
you power cycle the system.
== Why doesn't my package work?
Or a variation like...
@ -610,6 +720,79 @@ This means all packages have been built by a third party. If you
have an issue that's related to packaging, you will need to seek
help with whoever built it for you.
== My UPS is directly connected to an appliance with a limited version of NUT, how can I monitor the UPS from arbitrary clients?
You can set up a separate general-purpose system as the NUT server for
your "arbitrary clients", using `dummy-ups` in "relay mode" as the driver.
This instance of `dummy-ups` would in turn be the NUT client allowed to
interact with the appliance and that way with the UPS connected there.
NOTE: The original question related to a NAS with NUT provided in its
firmware OS, that only allowed one or few clients and not a whole
rack's worth of client IP addresses.
== My networked UPS can't handle being monitored by dozens of NUT clients
Network management cards on many UPSes are rather puny appliances, often
known to either limit the amount of clients who may connect, for security
or performance reasons, or otherwise to crash or respond very slowly when
overwhelmed.
You may be better off reducing the amount of servers connected to the UPS
with the `snmp-ups`, `netxml-ups` or similar type of driver, and set up
other systems as clients of these NUT servers.
Developers who are working on NUT, its drivers, or further projects and
appliances based on NUT, and who need to monitor their UPS from multiple
systems using the complete NUT stack on each system (e.g. during testing),
can benefit from dedicating a separate general-purpose system as the NUT
server using the real (networked) driver for the UPS, while using the
`dummy-ups` in "relay mode" as the driver connected to this dedicated
server on each tested system.
== How can I setup NUT as a proxy (setup a server to forward/relay client data)?
This can easily be achieved by using the `dummy-ups` driver.
The `port` field acts as the reference to the "other" UPS served
by another NUT server.
Example with `dummy-ups` driver:
[proxy]
driver = dummy-ups
port = upsname@ip-or-hostname[:port]
desc = "UPS proxy for UPS upsname on server ip-or-hostname"
Also note that there is a `clone` driver with similar purpose,
which allows users to group clients to a particular outlet of
a device with a "real" driver running locally, and deal with
this output as if it was a normal UPS.
Here the `port` field references the driver socket name that
the "real" UPS driver is using. See its manual page for more
details and caveats.
Example with `clone` driver:
[realups]
driver = usbhid-ups
port = auto
[clone-outlet-1]
driver = clone
port = usbhid-ups-realups
load.on = outlet.1.load.on
load.off = outlet.1.load.off
load.status = outlet.1.status
[...]
This allows to group load attached to a separately manageable
outlet (or group of outlets) on larger UPS and ePDUs, in order
to power those devices on/off together. This may be also useful
to delegate management of feeds to devices for purposes like
hosting or supporting hardware for smaller teams sharing a rack
in a larger company.
== Why are there two copies of upsmon running?
It's not really two complete copies if your OS forks efficiently.
@ -645,20 +828,23 @@ into your distribution (potentially with unofficial packages).
Some OS distributions contain old versions of NUT. If your hardware is newer
than the NUT release, there is a good chance that support has not been added
yet. Please do not tell us you have the "latest version for Distro XYZ" - even
yet. Please do not tell us you have the "latest version for Distro XYZ" -- even
if the developers are familiar with that distribution, it helps others if you
quote the exact package version.
NOTE: check the release date on the version you have. If it's more
than about 6-12 months old, there's probably a newer stable tree
version out there.
version out there. As development happens actively, be sure to also
check if a custom build from Git (usually using the `master` branch
of NUT https://github.com/networkupstools/nut/ repository) has your
issue fixed by some kind soul already.
== I built NUT from Git, and it complains about lots of missing files. What happened?
If you are not actively developing a driver, can you use a snapshot instead?
The NUT instance of Buildbot generates tar files of the latest NUT source
after each successful build, and these snapshots include a prebuilt version of
the `./configure` script.
after each successful build, and these snapshots include a pre-built version
of the `./configure` script.
Otherwise, you will need recent versions of autoconf, automake, libtool,
asciidoc, a2x and its dependencies for DocBook/dblatex. Rather than publish a
@ -687,7 +873,12 @@ NUT. Changing the way a fundamental component works, such as USB support,
means a lot of testing to ensure that your fix does not break other drivers.
Sometimes patches are put on hold due to a feature freeze. If it
doesn't show up once the new version opens up, send it again.
doesn't show up once the new version opens up, please send it again.
It may also be much more productive to submit changes as pull requests via
https://github.com/networkupstools/nut/pulls so they are automatically
processed by the NUT CI farm across numerous target platforms, and
various inconsistencies can be diagnosed and fixed early.
== I'm not much of a programmer. How can I help?
@ -752,6 +943,8 @@ for you.
There is a small chance that the mailing list spam filter ate your message.
Check the list archives to see if your message appears there.
Also double-check that you have subscribed to the lists and completed
all the confirmation rituals of its engine.
Convincing the other subscribers that you've actually read down this
far might be useful. You might mention "queequeg" for better results.
@ -770,6 +963,10 @@ In addition, the mailing lists are publicly archived, and therefore easily
searchable. Chances are, you aren't the only person who will ever have that
question.
There are similar benefits to using the discussions on issue tracker at
https://github.com/networkupstools/nut/issues and if suitable, in the
currently open pull requests.
== If you want mailing list replies to go to the list, why don't you add a Reply-To: header?
We are not going to rehash all of the arguments for and against this in a
@ -782,6 +979,10 @@ If you're not a programmer, you can still help others by making
that protocol available. You might host the document somewhere and
send the URL to one of the mailing lists.
Posting an issue with attachments on
https://github.com/networkupstools/nut/issues
can also be helpful.
== How can you answer questions to situations that nobody's encountered yet? Isn't this a frequently asked questions file?
*Answer 1*
@ -796,6 +997,9 @@ The idea is to write it up in here so that nobody asks the mailing
list when it finally does get released.
== My UPS powers up immediately after a power failure instead of waiting for the batteries to recharge!
Or a variation like...
== My UPS (an APC as it happens) lacks the field "battery.charge.restart" -- so how will it know when to restart?
You can rig up a little hack to handle this issue in software.
@ -812,8 +1016,8 @@ where there's not enough battery capacity left for upsmon to do its thing.
Exactly how long to wait is a function of your UPS hardware, and will require
careful testing.
If this is too evil for you, buy another kind of UPS that will either wait for a
minimum amount of charge, a minimum amount of time, or both.
If this is too evil for you, buy another kind of UPS that will either wait for
a minimum amount of charge, a minimum amount of time, or both.
== I'm facing a power race
Or a variation like...
@ -838,12 +1042,17 @@ they won't be stuck in the halted state with the UPS running on line power.
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)
then
/usr/local/ups/sbin/upsdrvctl shutdown
/sbin/upsdrvctl shutdown
sleep 120
# uh oh, we never got shut down! (power race?)
reboot
fi
------

View file

@ -1,3 +1,10 @@
MAINTAINERCLEANFILES = Makefile.in .dirstamp
EXTRA_DIST =
# Is "egrep == grep -E" always valid? (maybe all a job for configure.ac)
EGREP = egrep
#EGREP = grep -E
IMAGE_FILES = images/asciidoc.png \
images/hostedby.png \
images/nut_layering.png \
@ -12,9 +19,10 @@ IMAGE_FILES = images/asciidoc.png \
images/old-cgi.png
# Only track here the local deps
SHARED_DEPS = nut-names.txt asciidoc.conf
SHARED_DEPS = nut-names.txt daisychain.txt asciidoc.conf asciidoc.txt
USER_MANUAL_DEPS = acknowledgements.txt cables.txt config-notes.txt \
config-prereqs.txt ci-farm-lxc-setup.txt \
configure.txt download.txt documentation.txt features.txt history.txt \
outlets.txt scheduling.txt security.txt support.txt user-manual.txt
@ -35,44 +43,107 @@ CABLES_IMAGES = images/cables/73-0724.png images/cables/940-0024C.jpg \
images/cables/mge-usb-rj45.jpg \
images/cables/SOLA-330.png
ALL_TXT_SRC = nut-names.txt $(USER_MANUAL_DEPS) $(DEVELOPER_GUIDE_DEPS) \
$(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt
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
NUT_SPELL_DICT = nut.dict
EXTRA_DIST = $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \
EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \
$(CABLES_IMAGES) $(NUT_SPELL_DICT) \
common.xsl xhtml.xsl chunked.xsl
common.xsl xhtml.xsl chunked.xsl asciidoc.txt
ASCIIDOC_HTML_SINGLE = user-manual.html \
developer-guide.html \
packager-guide.html \
solaris-usb.html \
cables.html \
FAQ.html
ASCIIDOC_HTML_CHUNKED = user-manual.chunked \
developer-guide.chunked \
packager-guide.chunked \
FAQ.html
solaris-usb.chunked \
cables.chunked \
FAQ.chunked
ASCIIDOC_PDF = user-manual.pdf \
developer-guide.pdf \
packager-guide.pdf \
solaris-usb.pdf \
cables.pdf \
FAQ.pdf
SUBDIRS = man
SUFFIXES = .txt .html .pdf
SUBDIRS = man cables
SUFFIXES = .txt .html .pdf -spellchecked
all: doc
# This list is defined by configure script choices and options:
check-local: @DOC_CHECK_LIST@
# This list is defined by configure script choices and options:
doc: @DOC_BUILD_LIST@
# This target can be called by developers to go around the configure
# script choices at their risk (e.g. missing tools are possible):
docs: pdf html-single html-chunked man-man html-man
all-docs: docs
check-docs: check-pdf check-html-single check-html-chunked check-man
pdf: $(ASCIIDOC_PDF)
# also build the HTML manpages with these targets
html-single: $(ASCIIDOC_HTML_SINGLE)
html-chunked: $(ASCIIDOC_HTML_CHUNKED)
# the "for" loops might better use $^ but it might be not portable
check-pdf: $(ASCIIDOC_PDF)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for F in $(ASCIIDOC_PDF) ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i 'PDF document' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; if test -n "$$FAILED" ; then \
echo "FAILED PDF sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED PDF sanity check"; exit 0
check-html-single: $(ASCIIDOC_HTML_SINGLE)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for F in $(ASCIIDOC_HTML_SINGLE) ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; if test -n "$$FAILED" ; then \
echo "FAILED HTML-single sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED HTML-single sanity check"; exit 0
check-html-chunked: $(ASCIIDOC_HTML_CHUNKED)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for D in $(ASCIIDOC_HTML_CHUNKED); do \
for F in "$$D"/*.html ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; \
for F in "$$D"/*.css ; do \
test -s "$$F" && { $(EGREP) -i 'CSS stylesheet' "$$F" > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; \
done; if test -n "$$FAILED" ; then \
echo "FAILED HTML-chunked sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED HTML-chunked sanity check"; exit 0
# Note: usually the results from man-page check will be reported twice:
# once as a SUBDIRS child makefile, and once via DOC_CHECK_LIST expansion
# Note: default `make all` in the man directory caters to drivers etc.
# chosen during configure script execution. The "all-man" and "all-html"
# rules build everything documented.
check-man all-man man-man all-html html-man:
cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile $@
man:
cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all
CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css
# Dirs to clean
clean-local:
rm -rf *.pdf *.html *.chunked docbook-xsl.css *.bak
rm -rf *.chunked *.bak tmp
### TODO: automatic dependency generation
# Add other directory deps (not for local EXTRA_DIST) and generated contents
@ -85,55 +156,258 @@ 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
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
# generating the chunked HTML. In this case, export the environment
# variable ASCIIDOC_VERBOSE to "-v", ie:
# $ ASCIIDOC_VERBOSE=-v make
A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) --attribute icons \
--xsltproc-opts "--nonet" \
--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 iconsdir=$(srcdir)/images \
A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \
--attribute=icons \
--xsltproc-opts="--nonet" \
--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=iconsdir="$(srcdir)/images" \
--attribute=badges \
--attribute=external_title \
--attribute tree_version=@TREE_VERSION@ \
-a toc -a numbered --destination-dir=.
--attribute=tree_version="@TREE_VERSION@" \
-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
# (and does affect PDF builds, as found during work on collision-avoidance -
# true with at least asciidoc/a2x versions 9.0.0rc2).
# For more details see issues https://github.com/asciidoc/asciidoc/issues/44
# and https://github.com/networkupstools/nut/pull/281 (in short, attempts
# to "fix" this warning broke NUT build). If this is to be retried later, see
# https://github.com/networkupstools/nut/pull/281/commits/fe17861c4ea12679b3ebfefa8a6d692d79d99f2d
# and do not forget to fix up docs/man/Makefile.am too ;)
.txt.html: common.xsl xhtml.xsl
$(A2X) $(A2X_COMMON_OPTS) --attribute=xhtml11_format --format=xhtml --xsl-file=$(srcdir)/xhtml.xsl $<
# NOTE: a2x tends to copy some files into its working area, preserving original
# permissions. If those files are read-only in origin (e.g. packaged stylesheet
# or our resources coming from EXTRA_DIST) the next a2x can not overwrite it.
# Also note that such hoarding of files has potential to break parallel builds
# (or cause them to produce undefined results if some bad timing happens).
# As a brutal workaround for the former problem, we chmod. For second one we
# might try magic with .SEQUENTIAL recipe hints, but that is gmake-dependent.
.txt.chunked: common.xsl chunked.xsl
$(A2X) $(A2X_COMMON_OPTS) --attribute=chunked_format --format=chunked --xsl-file=$(srcdir)/chunked.xsl $<
# Note that empirically it treats "destination-dir" as the source root for
# PDF generation (even though it claims the argument is ignored for non-HTML
# targets) so we have to provide the "images/" in this case. ONLY for PDF!
.txt.pdf: docinfo.xml
$(A2X) $(A2X_COMMON_OPTS) --attribute=pdf_format --format=pdf -a docinfo1 $<
# Note we only remove the original target (if present), if it is a directory -
# e.g. created by "html-chunked" targets.
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 ; \
case "$${A2X_OUTDIR}" in \
tmp/pdf.*) ln -s ../../images "./$${A2X_OUTDIR}" ;; \
esac; \
else A2X_OUTDIR='.' ; fi; \
if test -s "${builddir}/docbook-xsl.css" \
&& test -r "${builddir}/docbook-xsl.css" \
&& ! test -w "${builddir}/docbook-xsl.css" \
; then chmod u+w "${builddir}/docbook-xsl.css" ; fi ; \
chmod -R u+w "./$${A2X_OUTDIR}" || true; \
}
# When moving "*" hope a2x did not make any "hidden" files
# like ".*" that would be required for resulting documents.
# Leave the "images/" dir there, though.
# Otherwise, we would have to `find` them all.
DOCBUILD_END = { \
if test -n "$${A2X_OUTDIR}" && test "$${A2X_OUTDIR}" != '.' ; then \
chmod -R u+w "./$${A2X_OUTDIR}" || true; \
test -d "$@" && rm -rf "$@" || true ; \
mv -f "./$${A2X_OUTDIR}/$(@F)" ./ || exit ; \
mv -f "./$${A2X_OUTDIR}/"*.* ./ 2>/dev/null || true ; \
rm -rf "./$${A2X_OUTDIR}" ; \
fi ; \
}
# PORTABILITY NOTE: POSIX Make forbids the suffix rule definitions with
# prerequisites like done below, and GNU Make of some versions complains;
# https://www.gnu.org/software/make/manual/html_node/Error-Messages.html
# says the prerequisites were ignored while a suffix rule was created;
# eventually the POSIX stance would be taken to define a rule for a weird
# verbatim target file name with prerequisites:
# ../docs/Makefile:936: warning: ignoring prerequisites on suffix rule definition
# Changes from ".txt.pdf: docinfo.xml" to "*.pdf: docinfo.xml" = ".txt.pdf:"
# as done below may be pointless in the end (with regard to a portable way
# to trigger builds by a changed dependency), but at least predictable and
# not toxic.
*.html: common.xsl xhtml.xsl
.txt.html:
@A2X_OUTDIR="tmp/html-single.$(@F).$$$$" ; \
echo " DOC-HTML Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=xhtml11_format --format=xhtml --xsl-file=$(srcdir)/xhtml.xsl $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
*.chunked: common.xsl chunked.xsl
.txt.chunked:
@A2X_OUTDIR="tmp/html-chunked.$(@F).$$$$" ; \
echo " DOC-HTML-CHUNKED Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=chunked_format --format=chunked --xsl-file=$(srcdir)/chunked.xsl $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
# Note: non-HTML a2x modes may ignore the destination directory
*.pdf: docinfo.xml
.txt.pdf:
@A2X_OUTDIR="tmp/pdf.$(@F).$$$$" ; \
echo " DOC-PDF Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=pdf_format --format=pdf -a docinfo1 $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
if HAVE_ASPELL
# 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)?
# NOTE: ../ChangeLog is nowadays generated from commit messages, so
# 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
../tools/nut-scanner/README \
../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3
# Directory SPELLCHECK_SRC files are relative to. Overriden by other Makefiles.
SPELLCHECK_DIR = $(srcdir)
# Note: de-facto our documentation is beyond ASCII (at least in names of
# international committers). The grep tests below look if the aspell output
# contained something other than the OK lines (tagged with asterisk) and
# aspell's version (tagged with @) and if it did - those lines must be the
# spellcheck complaints. Empty OUT is ok.
# We also must indent the input, because certain piped-in characters are
# interpreted as commands, and seems this feature can not be turned off.
# See also http://aspell.net/man-html/Through-A-Pipe.html
# TODO: Is "grep -a" or "grep -b" (treat input as ascii/bin) portable enough?
# Set SPELLCHECK_ERROR_FATAL=no if there are some unavoidable issues
# due to spellchecking, to temporarily not fail builds due to this.
# For Travis CI in particular, see ci_build.sh in NUT codebase root.
SPELLCHECK_ERROR_FATAL = yes
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
ASPELL_ENV_LANG = en.UTF-8
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
# 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
# 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)
@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)"`" \
&& { if test -n "$$OUT" ; then OUT="`echo "$$OUT" | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' `" ; fi; \
test -z "$$OUT" ; } \
|| { RES=$$? ; \
echo "FAILED : Aspell reported errors here:" >&2 \
&& echo "----- vvv" >&2 \
&& echo "$$OUT" >&2 \
&& echo "----- ^^^" >&2 ; \
exit $$RES; } ; \
touch "$@"
spellcheck:
@for docsrc in $(SPELLCHECK_SRC); do \
echo "Spell checking on $$docsrc"; \
LANG=C $(ASPELL) -a -t -p $(NUT_SPELL_DICT) < $$docsrc | grep [^*]; \
done
# Interactively spell check all documentation source files
@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; \
$(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 proceeding to spellchecking job..."; \
else true; fi
@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; \
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"; \
done ; \
if test -n "$$FAILED" ; then \
echo "=====================================================================" ; \
echo "FAILED automatic spellcheck for the following sources (relative to `pwd`): $$FAILED" ; \
echo "=====================================================================" ; \
echo "Please 'cd $(abs_top_builddir) && make spellcheck-interactive'"; \
echo "to either fix document sources or update the dictionary of accepted"; \
echo "words and spellings listed in the '$(NUT_SPELL_DICT)' file there."; \
echo "Either way, please follow up by posting a pull request or a patch"; \
echo "to integrate your fixes into the common NUT codebase."; \
echo "=====================================================================" ; \
test x"$(SPELLCHECK_ERROR_FATAL)" = xno || exit 1; \
echo "NOTE: SPELLCHECK_ERROR_FATAL == no so this make does not break the build!"; \
echo "=====================================================================" ; \
fi >&2 ; exit 0
# Interactively spell check all documentation source files below (so a human
# can edit the documentation errors and/or add words to custom dictionary).
# Note that here we do not restrain reported issues, so this might catch more
# than the automated test above.
spellcheck-sortdict: $(abs_builddir)/$(NUT_SPELL_DICT).sorted
# Note that the source file may be not overwritable (distcheck, cdrom, ...),
# so we'd ignore that failure. But the practical use-case is a developer's
# in-tree workspace, so we want the working copy of the dictionary fixed up
# for easy `git diff`ing if possible.
# Note also that "$(<F)" is not POSIX portable, so we spell out the name var :(
$(abs_builddir)/$(NUT_SPELL_DICT).sorted: $(abs_srcdir)/$(NUT_SPELL_DICT)
@cp -pf $(abs_srcdir)/$(NUT_SPELL_DICT) $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting
@LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; ( \
WORDLIST="`tail -n +2 < "$<" | sort | uniq`"; \
WORDCOUNT="`echo "$$WORDLIST" | wc -l`"; \
head -1 < "$<" | while read P L C E ; do echo "$$P $$L $$WORDCOUNT $$E"; break; done ; \
echo "$$WORDLIST"; \
) > "$@"
@cp -f "$@" "$(abs_builddir)/$(NUT_SPELL_DICT)"
@if [ "$(abs_builddir)" != "$(abs_srcdir)" ] ; then \
cp -f "$@" "$<" || true ; \
cp -f "$(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting" "$(abs_srcdir)/" || true ; \
fi
DISTCLEANFILES = $(NUT_SPELL_DICT).bak-pre-sorting .$(NUT_SPELL_DICT).sorted $(NUT_SPELL_DICT).sorted
spellcheck-interactive:
@for docsrc in $(SPELLCHECK_SRC); do\
echo "Spell checking on $$docsrc"; \
LANG=C $(ASPELL) check -p $(NUT_SPELL_DICT) $$docsrc; \
done
@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"; \
done ; \
if test -n "$$FAILED" ; then \
echo "FAILED interactive spellcheck for the following sources (relative to `pwd`): $$FAILED" >&2 ; \
exit 1; \
fi ; exit 0
$(MAKE) spellcheck-sortdict
@echo "------------------------------------------------------------------------"; \
echo "Custom dictionary file $(NUT_SPELL_DICT) may have been updated now."; \
echo "Use 'git add -p docs/$(NUT_SPELL_DICT) && git checkout -- docs/$(NUT_SPELL_DICT) && make spellcheck-sortdict && git add -p docs/$(NUT_SPELL_DICT)'"; \
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 "------------------------------------------------------------------------"
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)
@echo " SKIP-ASPELL $@ : Documentation spell check not available since 'aspell' was not found." >&2
spellcheck:
@echo "Documentation spell check not available since 'aspell' was not found."
spellcheck-interactive:
@echo "Documentation spell check not available since 'aspell' was not found."
endif !HAVE_ASPELL
.PHONY: html html-single pdf
.PHONY: html html-chunked html-single pdf man

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -14,7 +14,17 @@
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@ -79,19 +89,24 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = docs
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/docinfo.xml.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
@ -100,11 +115,17 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = docinfo.xml
@ -143,7 +164,7 @@ am__recursive_targets = \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
distdir distdir-am
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
@ -164,6 +185,7 @@ am__define_uniq_tagged_files = \
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/docinfo.xml.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@ -197,6 +219,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -207,6 +230,7 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
@ -220,6 +244,7 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
@ -229,9 +254,12 @@ DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
# Is "egrep == grep -E" always valid? (maybe all a job for configure.ac)
EGREP = egrep
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -249,6 +277,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
@ -259,21 +289,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
@ -293,6 +331,9 @@ PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
@ -306,6 +347,7 @@ STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
@ -323,6 +365,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -336,6 +379,9 @@ datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
@ -361,12 +407,14 @@ pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdsystemshutdowndir = @systemdsystemshutdowndir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
@ -376,6 +424,11 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
MAINTAINERCLEANFILES = Makefile.in .dirstamp
EXTRA_DIST = $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \
$(CABLES_IMAGES) $(NUT_SPELL_DICT) common.xsl xhtml.xsl \
chunked.xsl asciidoc.txt
#EGREP = grep -E
IMAGE_FILES = images/asciidoc.png \
images/hostedby.png \
images/nut_layering.png \
@ -391,8 +444,9 @@ IMAGE_FILES = images/asciidoc.png \
# Only track here the local deps
SHARED_DEPS = nut-names.txt asciidoc.conf
SHARED_DEPS = nut-names.txt daisychain.txt asciidoc.conf asciidoc.txt
USER_MANUAL_DEPS = acknowledgements.txt cables.txt config-notes.txt \
config-prereqs.txt ci-farm-lxc-setup.txt \
configure.txt download.txt documentation.txt features.txt history.txt \
outlets.txt scheduling.txt security.txt support.txt user-manual.txt
@ -413,32 +467,36 @@ CABLES_IMAGES = images/cables/73-0724.png images/cables/940-0024C.jpg \
images/cables/mge-usb-rj45.jpg \
images/cables/SOLA-330.png
ALL_TXT_SRC = nut-names.txt $(USER_MANUAL_DEPS) $(DEVELOPER_GUIDE_DEPS) \
$(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt
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
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_HTML_SINGLE = user-manual.html \
developer-guide.html \
packager-guide.html \
solaris-usb.html \
cables.html \
FAQ.html
ASCIIDOC_HTML_CHUNKED = user-manual.chunked \
developer-guide.chunked \
packager-guide.chunked \
FAQ.html
solaris-usb.chunked \
cables.chunked \
FAQ.chunked
ASCIIDOC_PDF = user-manual.pdf \
developer-guide.pdf \
packager-guide.pdf \
solaris-usb.pdf \
cables.pdf \
FAQ.pdf
SUBDIRS = man
SUFFIXES = .txt .html .pdf
SUBDIRS = man cables
SUFFIXES = .txt .html .pdf -spellchecked
CLEANFILES = *.xml *.html *.pdf *-spellchecked docbook-xsl.css
### TODO: automatic dependency generation
# Add other directory deps (not for local EXTRA_DIST) and generated contents
@ -454,29 +512,114 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \
# generating the chunked HTML. In this case, export the environment
# variable ASCIIDOC_VERBOSE to "-v", ie:
# $ ASCIIDOC_VERBOSE=-v make
A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) --attribute icons \
--xsltproc-opts "--nonet" \
--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 iconsdir=$(srcdir)/images \
A2X_COMMON_OPTS = $(ASCIIDOC_VERBOSE) \
--attribute=icons \
--xsltproc-opts="--nonet" \
--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=iconsdir="$(srcdir)/images" \
--attribute=badges \
--attribute=external_title \
--attribute tree_version=@TREE_VERSION@ \
-a toc -a numbered --destination-dir=.
--attribute=tree_version="@TREE_VERSION@" \
-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
# (and does affect PDF builds, as found during work on collision-avoidance -
# true with at least asciidoc/a2x versions 9.0.0rc2).
# For more details see issues https://github.com/asciidoc/asciidoc/issues/44
# and https://github.com/networkupstools/nut/pull/281 (in short, attempts
# to "fix" this warning broke NUT build). If this is to be retried later, see
# https://github.com/networkupstools/nut/pull/281/commits/fe17861c4ea12679b3ebfefa8a6d692d79d99f2d
# and do not forget to fix up docs/man/Makefile.am too ;)
# NOTE: a2x tends to copy some files into its working area, preserving original
# permissions. If those files are read-only in origin (e.g. packaged stylesheet
# or our resources coming from EXTRA_DIST) the next a2x can not overwrite it.
# Also note that such hoarding of files has potential to break parallel builds
# (or cause them to produce undefined results if some bad timing happens).
# As a brutal workaround for the former problem, we chmod. For second one we
# might try magic with .SEQUENTIAL recipe hints, but that is gmake-dependent.
# Note that empirically it treats "destination-dir" as the source root for
# PDF generation (even though it claims the argument is ignored for non-HTML
# targets) so we have to provide the "images/" in this case. ONLY for PDF!
# Note we only remove the original target (if present), if it is a directory -
# e.g. created by "html-chunked" targets.
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 ; \
case "$${A2X_OUTDIR}" in \
tmp/pdf.*) ln -s ../../images "./$${A2X_OUTDIR}" ;; \
esac; \
else A2X_OUTDIR='.' ; fi; \
if test -s "${builddir}/docbook-xsl.css" \
&& test -r "${builddir}/docbook-xsl.css" \
&& ! test -w "${builddir}/docbook-xsl.css" \
; then chmod u+w "${builddir}/docbook-xsl.css" ; fi ; \
chmod -R u+w "./$${A2X_OUTDIR}" || true; \
}
# When moving "*" hope a2x did not make any "hidden" files
# like ".*" that would be required for resulting documents.
# Leave the "images/" dir there, though.
# Otherwise, we would have to `find` them all.
DOCBUILD_END = { \
if test -n "$${A2X_OUTDIR}" && test "$${A2X_OUTDIR}" != '.' ; then \
chmod -R u+w "./$${A2X_OUTDIR}" || true; \
test -d "$@" && rm -rf "$@" || true ; \
mv -f "./$${A2X_OUTDIR}/$(@F)" ./ || exit ; \
mv -f "./$${A2X_OUTDIR}/"*.* ./ 2>/dev/null || true ; \
rm -rf "./$${A2X_OUTDIR}" ; \
fi ; \
}
# 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)?
# NOTE: ../ChangeLog is nowadays generated from commit messages, so
# 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.
@HAVE_ASPELL_TRUE@SPELLCHECK_SRC = $(ALL_TXT_SRC) ../README ../INSTALL.nut ../UPGRADING ../NEWS \
@HAVE_ASPELL_TRUE@ ../TODO ../scripts/ufw/README ../scripts/augeas/README ../lib/README \
@HAVE_ASPELL_TRUE@ ../tools/nut-scanner/README
@HAVE_ASPELL_TRUE@ ../tools/nut-scanner/README \
@HAVE_ASPELL_TRUE@ ../AUTHORS ../COPYING ../LICENSE-GPL2 ../LICENSE-GPL3
# Directory SPELLCHECK_SRC files are relative to. Overriden by other Makefiles.
@HAVE_ASPELL_TRUE@SPELLCHECK_DIR = $(srcdir)
# Note: de-facto our documentation is beyond ASCII (at least in names of
# international committers). The grep tests below look if the aspell output
# contained something other than the OK lines (tagged with asterisk) and
# aspell's version (tagged with @) and if it did - those lines must be the
# spellcheck complaints. Empty OUT is ok.
# We also must indent the input, because certain piped-in characters are
# interpreted as commands, and seems this feature can not be turned off.
# See also http://aspell.net/man-html/Through-A-Pipe.html
# TODO: Is "grep -a" or "grep -b" (treat input as ascii/bin) portable enough?
# Set SPELLCHECK_ERROR_FATAL=no if there are some unavoidable issues
# due to spellchecking, to temporarily not fail builds due to this.
# For Travis CI in particular, see ci_build.sh in NUT codebase root.
@HAVE_ASPELL_TRUE@SPELLCHECK_ERROR_FATAL = yes
@HAVE_ASPELL_TRUE@SPELLCHECK_ENV_DEBUG = no
@HAVE_ASPELL_TRUE@ASPELL_NUT_COMMON_ARGS = -p \
@HAVE_ASPELL_TRUE@ $(abs_srcdir)/$(NUT_SPELL_DICT) -d en \
@HAVE_ASPELL_TRUE@ --lang=en --ignore-accents --encoding=utf-8
@HAVE_ASPELL_TRUE@ASPELL_ENV_LANG = en.UTF-8
@HAVE_ASPELL_TRUE@ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$)
@HAVE_ASPELL_TRUE@DISTCLEANFILES = $(NUT_SPELL_DICT).bak-pre-sorting .$(NUT_SPELL_DICT).sorted $(NUT_SPELL_DICT).sorted
all: all-recursive
.SUFFIXES:
.SUFFIXES: .txt .html .pdf .chunked
.SUFFIXES: .txt .html .pdf -spellchecked .chunked
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -489,14 +632,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu docs/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -615,7 +757,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -671,6 +816,7 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) check-local
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
@ -697,14 +843,17 @@ install-strip:
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
@ -769,65 +918,240 @@ ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.MAKE: $(am__recursive_targets) check-am install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-libtool clean-local \
cscopelist-am ctags ctags-am distclean distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am
check-am check-local clean clean-generic clean-libtool \
clean-local cscopelist-am ctags ctags-am distclean \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs installdirs-am \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
all: doc
# This list is defined by configure script choices and options:
check-local: @DOC_CHECK_LIST@
# This list is defined by configure script choices and options:
doc: @DOC_BUILD_LIST@
# This target can be called by developers to go around the configure
# script choices at their risk (e.g. missing tools are possible):
docs: pdf html-single html-chunked man-man html-man
all-docs: docs
check-docs: check-pdf check-html-single check-html-chunked check-man
pdf: $(ASCIIDOC_PDF)
# also build the HTML manpages with these targets
html-single: $(ASCIIDOC_HTML_SINGLE)
html-chunked: $(ASCIIDOC_HTML_CHUNKED)
# the "for" loops might better use $^ but it might be not portable
check-pdf: $(ASCIIDOC_PDF)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for F in $(ASCIIDOC_PDF) ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i 'PDF document' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; if test -n "$$FAILED" ; then \
echo "FAILED PDF sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED PDF sanity check"; exit 0
check-html-single: $(ASCIIDOC_HTML_SINGLE)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for F in $(ASCIIDOC_HTML_SINGLE) ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; if test -n "$$FAILED" ; then \
echo "FAILED HTML-single sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED HTML-single sanity check"; exit 0
check-html-chunked: $(ASCIIDOC_HTML_CHUNKED)
@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
for D in $(ASCIIDOC_HTML_CHUNKED); do \
for F in "$$D"/*.html ; do \
test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; \
for F in "$$D"/*.css ; do \
test -s "$$F" && { $(EGREP) -i 'CSS stylesheet' "$$F" > /dev/null ; } || FAILED="$$FAILED $$F" ; \
done; \
done; if test -n "$$FAILED" ; then \
echo "FAILED HTML-chunked sanity check for:$$FAILED" >&2 ; file $$FAILED >&2 ; exit 1; \
fi; echo "PASSED HTML-chunked sanity check"; exit 0
# Note: usually the results from man-page check will be reported twice:
# once as a SUBDIRS child makefile, and once via DOC_CHECK_LIST expansion
# Note: default `make all` in the man directory caters to drivers etc.
# chosen during configure script execution. The "all-man" and "all-html"
# rules build everything documented.
check-man all-man man-man all-html html-man:
cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile $@
man:
cd $(top_builddir)/docs/man/ && $(MAKE) -f Makefile all
# Dirs to clean
clean-local:
rm -rf *.pdf *.html *.chunked docbook-xsl.css *.bak
rm -rf *.chunked *.bak tmp
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
solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf
.txt.html: common.xsl xhtml.xsl
$(A2X) $(A2X_COMMON_OPTS) --attribute=xhtml11_format --format=xhtml --xsl-file=$(srcdir)/xhtml.xsl $<
# PORTABILITY NOTE: POSIX Make forbids the suffix rule definitions with
# prerequisites like done below, and GNU Make of some versions complains;
# https://www.gnu.org/software/make/manual/html_node/Error-Messages.html
# says the prerequisites were ignored while a suffix rule was created;
# eventually the POSIX stance would be taken to define a rule for a weird
# verbatim target file name with prerequisites:
# ../docs/Makefile:936: warning: ignoring prerequisites on suffix rule definition
# Changes from ".txt.pdf: docinfo.xml" to "*.pdf: docinfo.xml" = ".txt.pdf:"
# as done below may be pointless in the end (with regard to a portable way
# to trigger builds by a changed dependency), but at least predictable and
# not toxic.
*.html: common.xsl xhtml.xsl
.txt.html:
@A2X_OUTDIR="tmp/html-single.$(@F).$$$$" ; \
echo " DOC-HTML Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=xhtml11_format --format=xhtml --xsl-file=$(srcdir)/xhtml.xsl $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
.txt.chunked: common.xsl chunked.xsl
$(A2X) $(A2X_COMMON_OPTS) --attribute=chunked_format --format=chunked --xsl-file=$(srcdir)/chunked.xsl $<
*.chunked: common.xsl chunked.xsl
.txt.chunked:
@A2X_OUTDIR="tmp/html-chunked.$(@F).$$$$" ; \
echo " DOC-HTML-CHUNKED Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=chunked_format --format=chunked --xsl-file=$(srcdir)/chunked.xsl $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
.txt.pdf: docinfo.xml
$(A2X) $(A2X_COMMON_OPTS) --attribute=pdf_format --format=pdf -a docinfo1 $<
# Note: non-HTML a2x modes may ignore the destination directory
*.pdf: docinfo.xml
.txt.pdf:
@A2X_OUTDIR="tmp/pdf.$(@F).$$$$" ; \
echo " DOC-PDF Generating $@"; \
$(DOCBUILD_BEGIN) ; RES=0; \
$(A2X) $(A2X_COMMON_OPTS) --attribute=pdf_format --format=pdf -a docinfo1 $< || RES=$$? ; \
$(DOCBUILD_END) ; exit $$RES
# 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
# 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
# at a time, with an outer Makefile caller ensuring the looping:
@HAVE_ASPELL_TRUE@$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE) $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT)
@HAVE_ASPELL_TRUE@ @LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
@HAVE_ASPELL_TRUE@ rm -f "$@" || true ; \
@HAVE_ASPELL_TRUE@ echo " ASPELL Spell checking on $(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"; \
@HAVE_ASPELL_TRUE@ OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a -t $(ASPELL_NUT_COMMON_ARGS) 2>&1) < "$(SPELLCHECK_DIR)/$(SPELLCHECK_SRC_ONE)"`" \
@HAVE_ASPELL_TRUE@ && { if test -n "$$OUT" ; then OUT="`echo "$$OUT" | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' `" ; fi; \
@HAVE_ASPELL_TRUE@ test -z "$$OUT" ; } \
@HAVE_ASPELL_TRUE@ || { RES=$$? ; \
@HAVE_ASPELL_TRUE@ echo "FAILED : Aspell reported errors here:" >&2 \
@HAVE_ASPELL_TRUE@ && echo "----- vvv" >&2 \
@HAVE_ASPELL_TRUE@ && echo "$$OUT" >&2 \
@HAVE_ASPELL_TRUE@ && echo "----- ^^^" >&2 ; \
@HAVE_ASPELL_TRUE@ exit $$RES; } ; \
@HAVE_ASPELL_TRUE@ touch "$@"
@HAVE_ASPELL_TRUE@spellcheck:
@HAVE_ASPELL_TRUE@ @for docsrc in $(SPELLCHECK_SRC); do \
@HAVE_ASPELL_TRUE@ echo "Spell checking on $$docsrc"; \
@HAVE_ASPELL_TRUE@ LANG=C $(ASPELL) -a -t -p $(NUT_SPELL_DICT) < $$docsrc | grep [^*]; \
@HAVE_ASPELL_TRUE@ done
# Interactively spell check all documentation source files
@HAVE_ASPELL_TRUE@ @if test "$(SPELLCHECK_ENV_DEBUG)" != no ; then \
@HAVE_ASPELL_TRUE@ echo "ASPELL DEBUG : information about the setup follows:"; \
@HAVE_ASPELL_TRUE@ LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; \
@HAVE_ASPELL_TRUE@ $(ASPELL) --help || true; \
@HAVE_ASPELL_TRUE@ dpkg -l |grep -i aspell || true ; \
@HAVE_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)' )" ; \
@HAVE_ASPELL_TRUE@ echo "ASPELL proceeding to spellchecking job..."; \
@HAVE_ASPELL_TRUE@ else true; fi
@HAVE_ASPELL_TRUE@ @FAILED="" ; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
@HAVE_ASPELL_TRUE@ for docsrc in $(SPELLCHECK_SRC); do \
@HAVE_ASPELL_TRUE@ if test "$(SPELLCHECK_ENV_DEBUG)" != no ; then \
@HAVE_ASPELL_TRUE@ echo "ASPELL MAKEFILE DEBUG: Will see from `pwd` if '$(SPELLCHECK_DIR)/$${docsrc}-spellchecked' is up to date" >&2; \
@HAVE_ASPELL_TRUE@ else true ; fi ; \
@HAVE_ASPELL_TRUE@ $(MAKE) -s -f "$(abs_top_builddir)/docs/Makefile" SPELLCHECK_SRC_ONE="$${docsrc}" SPELLCHECK_DIR="$(SPELLCHECK_DIR)" "$(SPELLCHECK_DIR)/$${docsrc}-spellchecked" \
@HAVE_ASPELL_TRUE@ || FAILED="$$FAILED $(SPELLCHECK_DIR)/$$docsrc"; \
@HAVE_ASPELL_TRUE@ done ; \
@HAVE_ASPELL_TRUE@ if test -n "$$FAILED" ; then \
@HAVE_ASPELL_TRUE@ echo "=====================================================================" ; \
@HAVE_ASPELL_TRUE@ echo "FAILED automatic spellcheck for the following sources (relative to `pwd`): $$FAILED" ; \
@HAVE_ASPELL_TRUE@ echo "=====================================================================" ; \
@HAVE_ASPELL_TRUE@ echo "Please 'cd $(abs_top_builddir) && make spellcheck-interactive'"; \
@HAVE_ASPELL_TRUE@ echo "to either fix document sources or update the dictionary of accepted"; \
@HAVE_ASPELL_TRUE@ echo "words and spellings listed in the '$(NUT_SPELL_DICT)' file there."; \
@HAVE_ASPELL_TRUE@ echo "Either way, please follow up by posting a pull request or a patch"; \
@HAVE_ASPELL_TRUE@ echo "to integrate your fixes into the common NUT codebase."; \
@HAVE_ASPELL_TRUE@ echo "=====================================================================" ; \
@HAVE_ASPELL_TRUE@ test x"$(SPELLCHECK_ERROR_FATAL)" = xno || exit 1; \
@HAVE_ASPELL_TRUE@ echo "NOTE: SPELLCHECK_ERROR_FATAL == no so this make does not break the build!"; \
@HAVE_ASPELL_TRUE@ echo "=====================================================================" ; \
@HAVE_ASPELL_TRUE@ fi >&2 ; exit 0
# Interactively spell check all documentation source files below (so a human
# can edit the documentation errors and/or add words to custom dictionary).
# Note that here we do not restrain reported issues, so this might catch more
# than the automated test above.
@HAVE_ASPELL_TRUE@spellcheck-sortdict: $(abs_builddir)/$(NUT_SPELL_DICT).sorted
# Note that the source file may be not overwritable (distcheck, cdrom, ...),
# so we'd ignore that failure. But the practical use-case is a developer's
# in-tree workspace, so we want the working copy of the dictionary fixed up
# for easy `git diff`ing if possible.
# Note also that "$(<F)" is not POSIX portable, so we spell out the name var :(
@HAVE_ASPELL_TRUE@$(abs_builddir)/$(NUT_SPELL_DICT).sorted: $(abs_srcdir)/$(NUT_SPELL_DICT)
@HAVE_ASPELL_TRUE@ @cp -pf $(abs_srcdir)/$(NUT_SPELL_DICT) $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting
@HAVE_ASPELL_TRUE@ @LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; ( \
@HAVE_ASPELL_TRUE@ WORDLIST="`tail -n +2 < "$<" | sort | uniq`"; \
@HAVE_ASPELL_TRUE@ WORDCOUNT="`echo "$$WORDLIST" | wc -l`"; \
@HAVE_ASPELL_TRUE@ head -1 < "$<" | while read P L C E ; do echo "$$P $$L $$WORDCOUNT $$E"; break; done ; \
@HAVE_ASPELL_TRUE@ echo "$$WORDLIST"; \
@HAVE_ASPELL_TRUE@ ) > "$@"
@HAVE_ASPELL_TRUE@ @cp -f "$@" "$(abs_builddir)/$(NUT_SPELL_DICT)"
@HAVE_ASPELL_TRUE@ @if [ "$(abs_builddir)" != "$(abs_srcdir)" ] ; then \
@HAVE_ASPELL_TRUE@ cp -f "$@" "$<" || true ; \
@HAVE_ASPELL_TRUE@ cp -f "$(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting" "$(abs_srcdir)/" || true ; \
@HAVE_ASPELL_TRUE@ fi
@HAVE_ASPELL_TRUE@spellcheck-interactive:
@HAVE_ASPELL_TRUE@ @for docsrc in $(SPELLCHECK_SRC); do\
@HAVE_ASPELL_TRUE@ echo "Spell checking on $$docsrc"; \
@HAVE_ASPELL_TRUE@ LANG=C $(ASPELL) check -p $(NUT_SPELL_DICT) $$docsrc; \
@HAVE_ASPELL_TRUE@ done
@HAVE_ASPELL_TRUE@ @FAILED="" ; for docsrc in $(SPELLCHECK_SRC); do \
@HAVE_ASPELL_TRUE@ echo "Spell checking on $(SPELLCHECK_DIR)/$$docsrc"; \
@HAVE_ASPELL_TRUE@ LANG=$(ASPELL_ENV_LANG) LC_ALL=$(ASPELL_ENV_LANG) $(ASPELL) check $(ASPELL_NUT_COMMON_ARGS) $(SPELLCHECK_DIR)/$$docsrc || \
@HAVE_ASPELL_TRUE@ FAILED="$$FAILED $(SPELLCHECK_DIR)/$$docsrc"; \
@HAVE_ASPELL_TRUE@ done ; \
@HAVE_ASPELL_TRUE@ if test -n "$$FAILED" ; then \
@HAVE_ASPELL_TRUE@ echo "FAILED interactive spellcheck for the following sources (relative to `pwd`): $$FAILED" >&2 ; \
@HAVE_ASPELL_TRUE@ exit 1; \
@HAVE_ASPELL_TRUE@ fi ; exit 0
@HAVE_ASPELL_TRUE@ $(MAKE) spellcheck-sortdict
@HAVE_ASPELL_TRUE@ @echo "------------------------------------------------------------------------"; \
@HAVE_ASPELL_TRUE@ echo "Custom dictionary file $(NUT_SPELL_DICT) may have been updated now."; \
@HAVE_ASPELL_TRUE@ echo "Use 'git add -p docs/$(NUT_SPELL_DICT) && git checkout -- docs/$(NUT_SPELL_DICT) && make spellcheck-sortdict && git add -p docs/$(NUT_SPELL_DICT)'"; \
@HAVE_ASPELL_TRUE@ echo "to review changes (please DO NOT REMOVE LINES that aspell chose to drop,"; \
@HAVE_ASPELL_TRUE@ echo "because other systems might not know these words in their system dictionaries)"; \
@HAVE_ASPELL_TRUE@ echo "------------------------------------------------------------------------"
# This rule woulf probably just fail; normally with no ASPELL there are no callers for it
@HAVE_ASPELL_FALSE@*/*-spellchecked *-spellchecked: Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT)
@HAVE_ASPELL_FALSE@ @echo " SKIP-ASPELL $@ : Documentation spell check not available since 'aspell' was not found." >&2
@HAVE_ASPELL_FALSE@spellcheck:
@HAVE_ASPELL_FALSE@ @echo "Documentation spell check not available since 'aspell' was not found."
@HAVE_ASPELL_FALSE@spellcheck-interactive:
@HAVE_ASPELL_FALSE@ @echo "Documentation spell check not available since 'aspell' was not found."
.PHONY: html html-single pdf
.PHONY: html html-chunked html-single pdf man
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View file

@ -19,24 +19,24 @@ The NUT Team
Active members
~~~~~~~~~~~~~~
- Arnaud Quette: project leader (since 2005), Debian packager and jack of all trades
- 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
- Charles Lepple: senior lieutenant
- Emilien Kia: senior developer
- Daniele Pezzini: senior developer
- Václav Krpec: junior developer
- Kjell Claesson: senior developer
- Alexander Gordeev: junior developer
- Michal Soltys: junior developer
- David Goncalves: Python developer
- Jean Perriault: web consultant
- Eric S. Raymond: Documentation consultant
- Roger Price: Documentation specialist
- Oden Eriksson: Mandriva packager
- Stanislav Brabec: Novell / Suse packager
- Stanislav Brabec: Novell / SUSE packager
- Michal Hlavinka: Redhat packager
- Antoine Colombier: trainee
For an up to date list of NUT developers, refer to
link:https://github.com/orgs/networkupstools/members[GitHub].
link:https://github.com/networkupstools/nut/graphs/contributors[GitHub].
Retired members
~~~~~~~~~~~~~~~
@ -45,8 +45,8 @@ Retired members
- Arjen de Korte: senior lieutenant
- Peter Selinger: senior lieutenant
- Carlos Rodrigues: author of the "megatec" drivers, removing the numerous
drivers for Megatec / Q1 protocol. These drivers have now been replaced by
blazer_ser and blazer_usb
drivers for Megatec / Q1 protocol. These drivers have now been replaced
by blazer_ser and blazer_usb
- Niels Baggesen: ported and heavily extended upscode2 to NUT 2.0 driver model
- Niklas Edmundsson: has worked on 3-phase support, and upscode2 updates
- Martin Loyer: has worked a bit on mge-utalk
@ -57,6 +57,8 @@ blazer_ser and blazer_usb
- Julius Malkiewicz: junior developer
- Tomas Smetana: former Redhat packager (2007-2008)
- Frederic Bohe: senior developer, Eaton contractor (2009-2013)
- Emilien Kia: senior developer
- Václav Krpec: junior developer
Supporting manufacturers
@ -87,13 +89,20 @@ provide you with official support from Eaton, or a better level of device
support in NUT.*
================================================================================
* link:https://www.ametek.com/products/businessunits/powersystemsandinstruments/powervar[AMETEK
Powervar], through Andrew McCartney, has added support for all AMETEK Powervar
UPM models as usb-hid UPS.
* link:http://www.gamatronic.com[Gamatronic], through Nadav Moskovitch, has
revived the 'sec' driver (as gamatronic), and expanded a bit genericups for its
UPSs with alarm interface.
* link:https://ever.eu/[EVER Power Systems] added a USB HID subdriver for
EVER UPSes (Sinline RT Series, Sinline RT XL Series, ECO PRO AVR CDS Series).
* link:http://www.microdowell.com[Microdowell], through Elio Corbolante, has
created the 'microdowell' driver to support the Enterprise Nxx/Bxx serial devices.
They also proposes NUT as an alternative to its software for
created the 'microdowell' driver to support the Enterprise Nxx/Bxx serial
devices. The company also proposes NUT as an alternative to its software for
link:http://www.microdowell.com/fra/download.html[Linux / Unix].
* link:http://pcmups.com.tw[Powercom], through Alexey Morozov, has provided
@ -111,6 +120,13 @@ 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,
has added support for SNR-UPS-LID-XXXX models as usb-hid UPS.
* link:http://www.ablerex.com.tw/[Ablere Electronics Co., Ltd.] contributed
the ablerex subdriver for blazer_usb, handling Ablerex MP, ARES Plus, MSII
MSIII, GRs and GRs Plus models.
Appliances manufacturers
~~~~~~~~~~~~~~~~~~~~~~~~
@ -148,15 +164,16 @@ stance and quick responses to technical inquiries were appreciated for
making the development of the fentonups driver possible.
Fenton has since been acquired by link:http://www.metapo.com[Metapo].
- Bo Kersey of link:http://www.vircio.com[VirCIO] provided a Best Power Fortress
750 to facilitate the bestups driver.
- Bo Kersey of link:http://www.vircio.com[VirCIO] provided a Best Power
Fortress 750 to facilitate the bestups driver.
- Invensys Energy Systems provided the SOLA/Best "Phoenixtec" protocol
document. SOLA has since been acquired by Eaton.
- PowerKinetics technical support provided documentation on their MiniCOL
protocol, which is archived in the NUT protocol library.
PowerKinetics was acquired by the link:http://www.jst.cc[JST Group] in June 2003.
PowerKinetics was acquired by the link:http://www.jst.cc[JST Group]
in June 2003.
- link:http://www.cyberpowersystems.com[Cyber Power Systems] contributed a
700AVR model for testing and development of the cyberpower driver.
@ -166,7 +183,12 @@ and a UPStation GXT2 with the Web/SNMP card for development of the liebert
driver and expansion of the existing snmp-ups driver.
Liebert has since been acquired by link:http://www.emerson.com[Emerson].
NOTE: If a company or individual isn't listed here, then we probably don't have
enough information about the situation. Developers are requested to report vendor
contributions to the NUT team so this list may reflect their help.
If we have left you out, send us some mail.
NOTE: If a company or individual isn't listed here, then we probably don't
have enough information about the situation. Developers are kindly requested
to report vendor contributions to the NUT team so this list may reflect their
help, as well as convey a sense of official support (at least, that drivers
were proposed according to the know-how coming from specs and knowledge about
hardware and firmware capabilities, and not acquired via reverse engineering
with a certain degree of unreliability and incompleteness). If we have left
you out, please send us some mail or post a pull request to update this
document in GitHub.

19
docs/asciidoc.txt Normal file
View file

@ -0,0 +1,19 @@
Using AsciiDoc in NUT
=====================
Charles Lepple <clepple@gmail.com>
:Author Initials: CFL
Intro
-----
See the https://asciidoc-py.github.io/userguide.html[AsciiDoc User Guide]
for more information.
Works in Progress
-----------------
- link:website/index.html[The NUT Website]
- link:user-manual.html[The NUT User Manual]
- link:developer-guide.html[The NUT Developer Guide]
- link:packager-guide.html[The NUT Packager Guide]
- link:man/index.html[Man pages]

View file

@ -37,8 +37,8 @@ OmniGuard F6C***-RKM
*From "Daniel"*
A straight-through RS-232 cable (with pins 2-7 connected through) should work
with the following models:
A straight-through RS-232 cable (with pins 2-7 connected through) should
work with the following models:
- F6C110-RKM-2U
- F6C150-RKM-2U
@ -143,8 +143,8 @@ Contributed by Kjell Claesson and Arnaud Quette.
Phoenixtec (Best Power)
-----------------------
Many Best Power units (including the Patriot Pro II) have a female DB-9 socket
with a non-standard pinout.
Many Best Power units (including the Patriot Pro II) have a female DB-9
socket with a non-standard pinout.
|====
|Signal | PC | UPS
@ -166,7 +166,7 @@ Tripp-Lite
*From Tripp-Lite, via Bryan Kolodziej*
This cable (black 73-0844 cable) is used on various models, using the "Lan 2.2 interface"
and the genericups driver (upstype=5).
This cable (black 73-0844 cable) is used on various models, using the
"Lan 2.2 interface" and the genericups driver (upstype=5).
image::images/cables/73-0724.png[73-0724 cable]

2
docs/cables/Makefile.am Normal file
View file

@ -0,0 +1,2 @@
CLEANFILES = *-spellchecked
MAINTAINERCLEANFILES = Makefile.in .dirstamp

566
docs/cables/Makefile.in Normal file
View file

@ -0,0 +1,566 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = docs/cables
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
$(top_srcdir)/m4/ax_c_pragmas.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
$(top_srcdir)/m4/nut_check_libavahi.m4 \
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
$(top_srcdir)/m4/nut_check_libopenssl.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
$(top_srcdir)/m4/nut_check_python.m4 \
$(top_srcdir)/m4/nut_compiler_family.m4 \
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_stash_warnings.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A2X = @A2X@
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUGPARSE = @AUGPARSE@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPCHECK = @CPPCHECK@
CPPFLAGS = @CPPFLAGS@
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
CPPUNIT_LIBS = @CPPUNIT_LIBS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DBLATEX = @DBLATEX@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOC_BUILD_LIST = @DOC_BUILD_LIST@
DOC_CHECK_LIST = @DOC_CHECK_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DRVPATH = @DRVPATH@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDLIB_CONFIG = @GDLIB_CONFIG@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBAVAHI_CFLAGS = @LIBAVAHI_CFLAGS@
LIBAVAHI_LIBS = @LIBAVAHI_LIBS@
LIBDIR = @LIBDIR@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
LIBIPMI_LIBS = @LIBIPMI_LIBS@
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
LIBLTDL_LIBS = @LIBLTDL_LIBS@
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LIBS = @LIBNEON_LIBS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LIBS = @LIBNETSNMP_LIBS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LIBS = @LIBSSL_LIBS@
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_CONFIG = @LIBUSB_CONFIG@
LIBUSB_LIBS = @LIBUSB_LIBS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LIBS = @LIBWRAP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LN_S_R = @LN_S_R@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
NM = @NM@
NMEDIT = @NMEDIT@
NUT_DATADIR = @NUT_DATADIR@
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
NUT_NETVERSION = @NUT_NETVERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_NAME = @OS_NAME@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PIDPATH = @PIDPATH@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PORT = @PORT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SBINDIR = @SBINDIR@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SOURCE_HIGHLIGHT = @SOURCE_HIGHLIGHT@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
TREE_VERSION = @TREE_VERSION@
VALGRIND = @VALGRIND@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
XMLLINT = @XMLLINT@
XSLTPROC = @XSLTPROC@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
auglensdir = @auglensdir@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
cgiexecdir = @cgiexecdir@
datadir = @datadir@
datarootdir = @datarootdir@
devddir = @devddir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
hotplugdir = @hotplugdir@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
now = @now@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
systemdshutdowndir = @systemdshutdowndir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
CLEANFILES = *-spellchecked
MAINTAINERCLEANFILES = Makefile.in .dirstamp
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/cables/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu docs/cables/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
tags TAGS:
ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
cscopelist-am ctags-am distclean distclean-generic \
distclean-libtool distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View file

@ -11,6 +11,6 @@ FEMEA DB9 MACHO DB9
4/8 ---------- 5
5 ---------- 8
- This cable is working with Manager III 1300 VA and 650 VA, SMS Ups's
- Jump in computer side pins 4/8 and conect to pin 1 in UPS side
- This cable is working with Manager III 1300 VA and 650 VA, SMS UPS's
- Jump in computer side pins 4/8 and connect to pin 1 in UPS side
- Use NUT blazer_ser driver

693
docs/ci-farm-lxc-setup.txt Normal file
View file

@ -0,0 +1,693 @@
Setting up the multi-arch Linux LXC container farm for NUT CI
-------------------------------------------------------------
Due to some historical reasons including earlier personal experience,
the Linux container setup implemented as described below was done with
persistent LXC containers wrapped by LIBVIRT for management. There was
no particular use-case for systems like Docker (and no firepower for a
Kubernetes cluster) in that the build environment intended for testing
non-regression against a certain release does not need to be regularly
updated -- its purpose is to be stale and represent what users still
running that system for whatever reason (e.g. embedded, IoT, corporate)
have in their environments.
Common preparations
~~~~~~~~~~~~~~~~~~~
* Prepare LXC and LIBVIRT-LXC integration, including an "independent"
(aka "masqueraded) bridge for NAT, following https://wiki.debian.org/LXC
and https://wiki.debian.org/LXC/SimpleBridge
** For dnsmasq integration on the independent bridge (`lxcbr0` following
the documentation examples), be sure to mention:
*** `LXC_DHCP_CONFILE="/etc/lxc/dnsmasq.conf"` in `/etc/default/lxc-net`
*** `dhcp-hostsfile=/etc/lxc/dnsmasq-hosts.conf` in/as the content of
`/etc/lxc/dnsmasq.conf`
*** `touch /etc/lxc/dnsmasq-hosts.conf` which would list simple `name,IP`
pairs, one per line (so one per container)
*** `systemctl restart lxc-net` to apply config (is this needed after
setup of containers too, to apply new items before booting them?)
* Install qemu with its `/usr/bin/qemu-*-static` and registration in
`/var/lib/binfmt`
* Prepare an LVM partition (or preferably some other tech like ZFS)
as `/srv/libvirt` and create a `/srv/libvirt/rootfs` to hold the containers
* Prepare `/home/abuild` on the host system (preferably in ZFS with
lightweight compression like lz4 -- and optionally, only if the amount
of available system RAM permits, with deduplication; otherwise avoid it);
account user and group ID numbers are `399` as on the rest of the CI farm
(historically, inherited from OBS workers)
** It may help to generate an ssh key without a passphrase for `abuild`
that it would trust, to sub-login from CI agent sessions into the
container. Then again, it may be not required if CI logs into the
host by SSH using `authorized_keys` and an SSH Agent, and the inner
ssh client would forward that auth channel to the original agent.
+
------
abuild$ ssh-keygen
# accept defaults
abuild$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
abuild$ chmod 640 ~/.ssh/authorized_keys
------
* Edit the root (or whoever manages libvirt) `~/.profile` to default the
virsh provider with:
+
------
LIBVIRT_DEFAULT_URI=lxc:///system
export LIBVIRT_DEFAULT_URI
------
* If host root filesystem is small, relocate the LXC download cache to the
(larger) `/srv/libvirt` partition:
+
------
:; mkdir -p /srv/libvirt/cache-lxc
:; rm -rf /var/cache/lxc
:; ln -sfr /srv/libvirt/cache-lxc /var/cache/lxc
------
** Maybe similarly relocate shared `/home/abuild` to reduce strain on rootfs?
Setup a container
~~~~~~~~~~~~~~~~~
Note that completeness of qemu CPU emulation varies, so not all distros
can be installed, e.g. "s390x" failed for both debian10 and debian11 to
set up the `openssh-server` package, or once even to run `/bin/true` (seems
to have installed an older release though, to match the outdated emulation?)
While the `lxc-create` tool does not really specify the error cause and
deletes the directories after failure, it shows the pathname where it
writes the log (also deleted). Before re-trying the container creation, this
file can be watched with e.g. `tail -F /var/cache/lxc/.../debootstrap.log`
[NOTE]
======
You can find the list of LXC "template" definitions on your system
by looking at the contents of the `/usr/share/lxc/templates/` directory,
e.g. a script named `lxc-debian` for the "debian" template. You can see
further options for each "template" by invoking its help action, e.g.:
------
:; lxc-create -t debian -h
------
======
* Install containers like this:
+
------
:; lxc-create -P /srv/libvirt/rootfs \
-n jenkins-debian11-mips64el -t debian -- \
-r bullseye -a mips64el
------
** to specify a particular mirror (not everyone hosts everything --
so if you get something like
`"E: Invalid Release file, no entry for main/binary-mips/Packages"`
then see https://www.debian.org/mirror/list for details, and double-check
the chosen site to verify if the distro version of choice is hosted with
your arch of choice):
+
------
:; MIRROR="http://ftp.br.debian.org/debian/" \
lxc-create -P /srv/libvirt/rootfs \
-n jenkins-debian10-mips -t debian -- \
-r buster -a mips
------
** ...or for EOLed distros, use the archive, e.g.:
+
------
:; MIRROR="http://archive.debian.org/debian-archive/debian/" \
lxc-create -P /srv/libvirt/rootfs \
-n jenkins-debian8-s390x -t debian -- \
-r jessie -a s390x
------
** ...Alternatively, other distributions can be used (as supported by your
LXC scripts, typically in `/usr/share/debootstrap/scripts`), e.g. Ubuntu:
+
------
:; lxc-create -P /srv/libvirt/rootfs \
-n jenkins-ubuntu1804-s390x -t ubuntu -- \
-r bionic -a s390x
------
** For distributions with a different packaging mechanism from that on the
LXC host system, you may need to install corresponding tools (e.g. `yum4`,
`rpm` and `dnf` on Debian hosts for installing CentOS and related guests).
You may also need to pepper with symlinks to taste (e.g. `yum => yum4`),
or find a `pacman` build to install Arch Linux or derivative, etc.
Otherwise, you risk seeing something like this:
+
------
root@debian:~# lxc-create -P /srv/libvirt/rootfs \
-n jenkins-centos7-x86-64 -t centos -- \
-R 7 -a x86_64
Host CPE ID from /etc/os-release:
'yum' command is missing
lxc-create: jenkins-centos7-x86-64: lxccontainer.c:
create_run_template: 1616 Failed to create container from template
lxc-create: jenkins-centos7-x86-64: tools/lxc_create.c:
main: 319 Failed to create container jenkins-centos7-x86-64
------
+
Note also that with such "third-party" distributions you may face other
issues; for example, the CentOS helper did not generate some fields in
the `config` file that were needed for conversion into libvirt "domxml"
(as found by trial and error, and comparison to other `config` files):
+
------
lxc.uts.name = jenkins-centos7-x86-64
lxc.arch = x86_64
------
+
Also note the container/system naming without underscore in "x86_64" --
the deployed system discards the character when assigning its hostname.
Using "amd64" is another reasonable choice here.
* Add the "name,IP" line for this container to `/etc/lxc/dnsmasq-hosts.conf`
on the host, e.g.:
+
------
jenkins-debian11-mips,10.0.3.245
------
+
NOTE: Don't forget to eventually `systemctl restart lxc-net` to apply the
new host reservation!
* Convert a pure LXC container to be managed by LIBVIRT-LXC (and edit config
markup on the fly -- e.g. fix the LXC `dir:/` URL schema):
+
------
:; virsh -c lxc:///system domxml-from-native lxc-tools \
/srv/libvirt/rootfs/jenkins-debian11-armhf/config \
| sed -e 's,dir:/srv,/srv,' \
> /tmp/x && virsh define /tmp/x
------
+
NOTE: You may want to tune the default generic 64MB RAM allocation,
so your launched QEMU containers are not OOM-killed as they exceeded
their memory `cgroup` limit. In practice they do not eat *that much*
resident memory, just want to have it addressable by VMM, I guess
(swap is not very used either), at least not until active builds
start (and then it depends on compiler appetite and `make` program
parallelism level you allow, e.g. by pre-exporting `MAXPARMAKES`
environment variable for `ci_build.sh`, and on the number of Jenkins
"executors" assigned to the build agent).
+
** It may be needed to revert the generated "os/arch" to `x86_64` (and let
QEMU handle the rest) in the `/tmp/x` file, and re-try the definition:
+
------
:; virsh define /tmp/x
------
* Then execute `virsh edit jenkins-debian11-armhf` (and same for other
containers) to bind-mount the common `/home/abuild` location, adding
this tag to their "devices":
+
------
<filesystem type='mount' accessmode='passthrough'>
<source dir='/home/abuild'/>
<target dir='/home/abuild'/>
</filesystem>
------
** Note that generated XML might not conform to current LXC schema, so it
fails validation during save; this can be bypassed with `i` when it asks.
One such case was however with indeed invalid contents, the "dir:" schema
removed by example above.
Shepherd the herd
~~~~~~~~~~~~~~~~~
* Monitor deployed container rootfs'es with:
+
------
:; du -ks /srv/libvirt/rootfs/*
------
+
(should have non-trivial size for deployments without fatal infant errors)
* Mass-edit/review libvirt configurations with:
+
------
:; virsh list --all | awk '{print $2}' \
| grep jenkins | while read X ; do \
virsh edit --skip-validate $X ; done
------
** ...or avoid `--skip-validate` when markup is initially good :)
* Mass-define network interfaces:
+
------
:; virsh list --all | awk '{print $2}' \
| grep jenkins | while read X ; do \
virsh dumpxml "$X" | grep "bridge='lxcbr0'" \
|| virsh attach-interface --domain "$X" --config \
--type bridge --source lxcbr0 ; \
done
------
* Verify that unique MAC addresses were defined (e.g. `00:16:3e:00:00:01`
tends to pop up often, while `52:54:00:xx:xx:xx` are assigned to other
containers); edit the domain definitions to randomize, if needed:
+
------
:; grep 'mac add' /etc/libvirt/lxc/*.xml | awk '{print $NF" "$1}' | sort
------
* Make sure at least one console device exists (end of file, under the
network interface definition tags), e.g.:
+
------
<console type='pty'>
<target type='lxc' port='0'/>
</console>
------
* Populate with `abuild` account, as well as with the `bash` shell and
`sudo` ability, reporting of assigned IP addresses on the console,
and SSH server access complete with envvar passing from CI clients
by virtue of `ssh -o SendEnv='*' container-name`:
+
------
:; for ALTROOT in /srv/libvirt/rootfs/*/rootfs/ ; do \
echo "=== $ALTROOT :" >&2; \
grep eth0 "$ALTROOT/etc/issue" || ( printf '%s %s\n' \
'\S{NAME} \S{VERSION_ID} \n \l@\b ;' \
'Current IP(s): \4{eth0} \4{eth1} \4{eth2} \4{eth3}' \
>> "$ALTROOT/etc/issue" ) ; \
grep eth0 "$ALTROOT/etc/issue.net" || ( printf '%s %s\n' \
'\S{NAME} \S{VERSION_ID} \n \l@\b ;' \
'Current IP(s): \4{eth0} \4{eth1} \4{eth2} \4{eth3}' \
>> "$ALTROOT/etc/issue.net" ) ; \
groupadd -R "$ALTROOT" -g 399 abuild ; \
useradd -R "$ALTROOT" -u 399 -g abuild -M -N -s /bin/bash abuild \
|| useradd -R "$ALTROOT" -u 399 -g 399 -M -N -s /bin/bash abuild \
|| { if ! grep -w abuild "$ALTROOT/etc/passwd" ; then \
echo 'abuild:x:399:399::/home/abuild:/bin/bash' \
>> "$ALTROOT/etc/passwd" ; \
echo "USERADDed manually: passwd" >&2 ; \
fi ; \
if ! grep -w abuild "$ALTROOT/etc/shadow" ; then \
echo 'abuild:!:18889:0:99999:7:::' >> "$ALTROOT/etc/shadow" ; \
echo "USERADDed manually: shadow" >&2 ; \
fi ; \
} ; \
if [ -s "$ALTROOT/etc/ssh/sshd_config" ]; then \
grep 'AcceptEnv \*' "$ALTROOT/etc/ssh/sshd_config" || ( \
( echo "" ; \
echo "# For CI: Allow passing any envvars:"; \
echo 'AcceptEnv *' ) \
>> "$ALTROOT/etc/ssh/sshd_config" \
) ; \
fi ; \
done
------
+
Note that for some reason, in some of those other-arch distros `useradd`
fails to find the group anyway; then we have to "manually" add them.
* Let the host know and resolve the names/IPs of containers you assigned:
+
------
:; grep -v '#' /etc/lxc/dnsmasq-hosts.conf \
| while IFS=, read N I ; do \
getent hosts "$N" >&2 || echo "$I $N" ; \
done >> /etc/hosts
------
Further setup of the containers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See NUT `docs/config-prereqs.txt` about dependency package installation
for Debian-based Linux systems.
It may be wise to not install e.g. documentation generation tools (or at
least not the full set for HTML/PDF generation) in each environment, in
order to conserve space and run-time stress.
Still, if there are significant version outliers (such as using an older
distribution due to vCPU requirements), it can be installed fully just
to ensure non-regression -- e.g. that when adapting `Makefile` rule
definitions or compiler arguments to modern toolkits, we do not lose
the ability to build with older ones.
For this, `chroot` from the host system can be used, e.g. to improve the
interactive usability for a population of Debian(-compatible) containers
(and to use its networking, while the operating environment in containers
may be not yet configured or still struggling to access the Internet):
------
:; for ALTROOT in /srv/libvirt/rootfs/*/rootfs/ ; do \
echo "=== $ALTROOT :" ; \
chroot "$ALTROOT" apt-get install \
sudo bash vim mc p7zip p7zip-full pigz pbzip2 git \
; done
------
Similarly for `yum`-managed systems (CentOS and relatives), though specific
package names can differ, and additional package repositories may need to
be enabled first (see link:config-prereqs.txt[config-prereqs.txt] for more
details such as recommended package names).
Note that technically `(sudo) chroot ...` can also be used from the CI worker
account on the host system to build in the prepared filesystems without the
overhead of running containers as complete operating environments with any
standard services and several copies of Jenkins `agent.jar` in them.
Also note that externally-driven set-up of some packages, including the
`ca-certificates` and the JDK/JRE, require that the `/proc` filesystem
is usable in the chroot environment. This can be achieved with e.g.:
------
:; for ALTROOT in /srv/libvirt/rootfs/*/rootfs/ ; do \
for D in proc ; do \
echo "=== $ALTROOT/$D :" ; \
mkdir -p "$ALTROOT/$D" ; \
mount -o bind,rw "/$D" "$ALTROOT/$D" ; \
done ; \
done
------
TODO: Test and document a working NAT and firewall setup for this, to allow
SSH access to the containers via dedicated TCP ports exposed on the host.
Troubleshooting
~~~~~~~~~~~~~~~
* Q: Container won't start, its `virsh console` says something like:
+
------
Failed to create symlink /sys/fs/cgroup/net_cls: Operation not permitted
------
A: According to https://bugzilla.redhat.com/show_bug.cgi?id=1770763
(skip to the end for summary) this can happen when a newer Linux
host system with `cgroupsv2` capabilities runs an older guest distro
which only knows about `cgroupsv1`, such as when hosting a CentOS 7
container on a Debian 11 server.
** One workaround is to ensure that the guest `systemd` does not try to
"join" host facilities, by setting an explicit empty list for that:
+
------
:; echo 'JoinControllers=' >> "$ALTROOT/etc/systemd/system.conf"
------
** Another approach is to upgrade `systemd` related packages in the guest
container. This may require additional "backport" repositories or
similar means, possibly maintained not by distribution itself but by
other community members, and arguably would logically compromise the
idea of non-regression builds in the old environment "as is".
* Q: Server was set up with ZFS as recommended, and lots of I/O hit the
disk even when application writes are negligible
+
A: This was seen on some servers and generally derives from data layout
and how ZFS maintains the tree structure of blocks. A small application
write (such as a new log line) means a new empty data block allocation,
an old block release, and bubble up through the whole metadata tree to
complete the transaction (grouped as TXG to flush to disk).
+
** One solution is to use discardable build workspaces in RAM-backed
storage like `/dev/shm` (`tmpfs`) on Linux, or `/tmp` (`swap`) on
illumos hosting systems, and only use persistent storage for the home
directory with `.ccache` and `.gitcache-dynamatrix` directories.
** Another solution is to reduce the frequency of TXG sync from modern
default of 5 sec to conservative 30-60 sec. Check how to set the
`zfs_txg_timeout` on your platform.
Connecting Jenkins to the containers
------------------------------------
To properly cooperate with the
https://github.com/networkupstools/jenkins-dynamatrix[jenkins-dynamatrix]
project driving regular NUT CI builds, each build environment should be
exposed as an individual agent with labels describing its capabilities.
Agent Labels
~~~~~~~~~~~~
With the `jenkins-dynamatrix`, agent labels are used to calculate a large
"slow build" matrix to cover numerous scenarios for what can be tested
with the current population of the CI farm, across operating systems,
`make`, shell and compiler implementations and versions, and C/C++ language
revisions, to name a few common "axes" involved.
Labels for QEMU
^^^^^^^^^^^^^^^
Emulated-CPU container builds are CPU-intensive, so for them we define as
few capabilities as possible: here CI is more interested in checking how
binaries behave on those CPUs, *not* in checking the quality of recipes
(distcheck, Make implementations, etc.), shell scripts or documentation,
which is more efficient to test on native platforms.
Still, we are interested in results from different compiler suites, so
specify at least one version of each.
NOTE: Currently the NUT `Jenkinsfile-dynamatrix` only looks at various
`COMPILER` variants for `qemu-nut-builder` use-cases, disregarding the
versions and just using one that the environment defaults to.
The reduced set of labels for QEMU workers looks like:
------
qemu-nut-builder qemu-nut-builder:alldrv
NUT_BUILD_CAPS=drivers:all NUT_BUILD_CAPS=cppunit
OS_FAMILY=linux OS_DISTRO=debian11 GCCVER=10 CLANGVER=11
COMPILER=GCC COMPILER=CLANG
ARCH64=ppc64le ARCH_BITS=64
------
Labels for native builds
^^^^^^^^^^^^^^^^^^^^^^^^
For contrast, a "real" build agent's set of labels, depending on
presence or known lack of some capabilities, looks something like this:
------
doc-builder nut-builder nut-builder:alldrv
NUT_BUILD_CAPS=docs:man NUT_BUILD_CAPS=docs:all
NUT_BUILD_CAPS=drivers:all NUT_BUILD_CAPS=cppunit=no
OS_FAMILY=bsd OS_DISTRO=freebsd12 GCCVER=10 CLANGVER=10
COMPILER=GCC COMPILER=CLANG
ARCH64=amd64 ARCH_BITS=64
SHELL_PROGS=sh SHELL_PROGS=dash SHELL_PROGS=zsh SHELL_PROGS=bash
SHELL_PROGS=csh SHELL_PROGS=tcsh SHELL_PROGS=busybox
MAKE=make MAKE=gmake
PYTHON=python2.7 PYTHON=python3.8
------
Generic agent attributes
~~~~~~~~~~~~~~~~~~~~~~~~
* Name: e.g. `ci-debian-altroot--jenkins-debian10-arm64` (note the
pattern for "Conflicts With" detailed below)
* Remote root directory: preferably unique per agent, to avoid surprises;
e.g.: `/home/abuild/jenkins-nut-altroots/jenkins-debian10-armel`
** Note it may help that the system home directory itself is shared between
co-located containers, so that the `.ccache` or `.gitcache-dynamatrix`
are available to all builders with identical contents
** If RAM permits, the Jenkins Agent working directory may be placed in
a temporary filesystem not backed by disk (e.g. `/dev/shm` on modern
Linux distributions); roughly estimate 300Mb per executor for NUT builds.
* Usage: "Only build jobs with label expressions matching this node"
* Node properties / Environment variables:
** `PATH+LOCAL` => `/usr/lib/ccache`
Where to run agent.jar
~~~~~~~~~~~~~~~~~~~~~~
Depending on circumstances of the container, there are several options
available to the NUT CI farm:
* Java can run in the container, efficiently (native CPU, different distro)
=> the container may be exposed as a standalone host for direct SSH access
(usually by NAT, exposing SSH on a dedicated port of the host; or by first
connecting the Jenkins controller with the host as an SSH Build Agent, and
then calling SSH to the container as a prefix for running the agent; or
by using Jenkins Swarm agents), so ultimately the build `agent.jar` JVM
would run in the container.
Filesystem for the `abuild` account may be or not be shared with the host.
* Java can not run in the container (crashes on emulated CPU, or is too old
in the agent container's distro -- currently Jenkins requires JRE 8+, but
eventually will require 11+) => the agent would run on the host, and then
the host would `ssh` or `chroot` (networking not required, but bind-mount
of `/home/abuild` and maybe other paths from host would be needed) called
for executing `sh` steps in the container environment. Either way, home
directory of the `abuild` account is maintained on the host and shared with
the guest environment, user and group IDs should match.
* Java is inefficient in the container (operations like un-stashing the source
succeed but take minutes instead of seconds) => either of the above
Using Jenkins SSH Build Agents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a typical use-case for tightly integrated build farms under common
management, where the Jenkins controller can log by SSH into systems which
act as its build agents. It injects and launches the `agent.jar` to execute
child processes for the builds, and maintains a tunnel to communicate.
Methods below involving SSH assume that you have configured a password-less
key authentication from the host machine to the `abuild` account in each
guest build environment container.
This can be an `ssh-keygen` result posted into `authorized_keys`, or a
trusted key passed by a chain of ssh agents from a Jenkins Credential
for connection to the container-hoster into the container.
The private SSH key involved may be secured by a pass-phrase, as long as
your Jenkins Credential storage knows it too.
Note that for the approaches explored below, the containers are not
directly exposed for log-in from any external network.
* For passing the agent through an SSH connection from host to container,
so that the `agent.jar` runs inside the container environment, configure:
** Launch method: "Agents via SSH"
** Host, Credentials, Port: as suitable for accessing the container-hoster
+
NOTE: The container-hoster should have accessed the guest container from
the account used for intermediate access, e.g. `abuild`, so that its
`.ssh/known_hosts` file would trust the SSH server on the container.
** Prefix Start Agent Command: content depends on the container name,
but generally looks like the example below to report some info about
the final target platform (and make sure `java` is usable) in the
agent's log. Note that it ends with un-closed quote and a space char:
+
------
ssh jenkins-debian10-amd64 '( java -version & uname -a ; getconf LONG_BIT; getconf WORD_BIT; wait ) &&
------
** Suffix Start Agent Command: a single quote to close the text opened above:
------
'
------
* The other option is to run the `agent.jar` on the host, for all the
network and filesystem magic the agent does, and only execute shell
steps in the container. The solution relies on overridden `sh` step
implementation in the `jenkins-dynamatrix` shared library that uses a
magic `CI_WRAP_SH` environment variable to execute a pipe into the
container. Such pipes can be `ssh` or `chroot` with appropriate host
setup described above.
+
NOTE: In case of ssh piping, remember that the container's
`/etc/ssh/sshd_config` should `AcceptEnv *` and the SSH
server should be restarted after such configuration change.
** Launch method: "Agents via SSH"
** Host, Credentials, Port: as suitable for accessing the container-hoster
** Prefix Start Agent Command: content depends on the container name,
but generally looks like the example below to report some info about
the final target platform (and make sure it is accessible) in the
agent's log. Note that it ends with a space char, and that the command
here should not normally print anything into stderr/stdout (this tends
to confuse the Jenkins Remoting protocol):
+
------
echo PING > /dev/tcp/jenkins-debian11-ppc64el/22 &&
------
** Suffix Start Agent Command: empty
* Node properties / Environment variables:
** `CI_WRAP_SH` =>
+
------
ssh -o SendEnv='*' "jenkins-debian11-ppc64el" /bin/sh -xe
------
Using Jenkins Swarm Agents
^^^^^^^^^^^^^^^^^^^^^^^^^^
This approach allows remote systems to participate in the NUT CI farm by
dialing in and so defining an agent. A single contributing system may be
running a number of containers or virtual machines set up following the
instructions above, and each of those would be a separate build agent.
Such systems should be "dedicated" to contribution in the sense that
they should be up and connected for days, and sometimes tasks would land.
Configuration files maintained on the Swarm Agent system dictate which
labels or how many executors it would expose, etc. Credentials to access
the NUT CI farm Jenkins controller to register as an agent should be
arranged with the farm maintainers, and currently involve a GitHub account
with Jenkins role assignment for such access, and a token for authentication.
The https://github.com/networkupstools/jenkins-swarm-nutci[jenkins-swarm-nutci]
repository contains example code from such setup with a back-up server
experiment for the NUT CI farm, including auto-start method scripts for
Linux systemd and upstart, illumos SMF, and OpenBSD rcctl.
Sequentializing the stress
~~~~~~~~~~~~~~~~~~~~~~~~~~
Running one agent at a time
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Another aspect of farm management is that emulation is a slow and intensive
operation, so we can not run all agents and execute builds at the same time.
The current solution relies on
https://github.com/jimklimov/conflict-aware-ondemand-retention-strategy-plugin
to allow co-located build agents to "conflict" with each other -- when one
picks up a job from the queue, it blocks neighbors from starting; when it
is done, another may start.
Containers can be configured with "Availability => On demand", with shorter
cycle to switch over faster (the core code sleeps a minute between attempts):
* In demand delay: `0`;
* Idle delay: `0` (Jenkins may change it to `1`);
* Conflicts with: `^ci-debian-altroot--.*$` assuming that is the pattern
for agent definitions in Jenkins -- not necessarily linked to hostnames.
Also, the "executors" count should be reduced to the amount of compilers
in that system (usually 2) and so avoid extra stress of scheduling too many
emulated-CPU builds at once.
Sequentializing the git cache access
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As part of the `jenkins-dynamatrix` optional optimizations, the NUT CI
recipe invoked via `Jenkinsfile-dynamatrix` maintains persistent git
reference repositories that can be used to cache NUT codebase (including
the tested commits) and so considerably speed up workspace preparation
when running numerous build scenarios on the same agent.
Such `.gitcache-dynamatrix` cache directories are located in the build
workspace location (unique for each agent), but on a system with numerous
containers these names can be symlinks pointing to a shared location.
To avoid collisions with several executors updating the same cache with
new commits, critical access windows are sequentialized with the use of
https://github.com/jenkinsci/lockable-resources-plugin[Lockable Resources
plugin]. On the `jenkins-dynamatrix` side this is facilitated by labels:
------
DYNAMATRIX_UNSTASH_PREFERENCE=scm-ws:nut-ci-src
DYNAMATRIX_REFREPO_WORKSPACE_LOCKNAME=gitcache-dynamatrix:SHARED_HYPERVISOR_NAME
------
* The `DYNAMATRIX_UNSTASH_PREFERENCE` tells the `jenkins-dynamatrix` library
code which checkout/unstash strategy to use on a particular build agent
(following values defined in the library; `scm-ws` means SCM caching
under the agent workspace location, `nut-ci-src` names the cache for
this project);
* The `DYNAMATRIX_REFREPO_WORKSPACE_LOCKNAME` specifies a semi-unique
string: it should be same for all co-located agents which use the same
shared cache location, e.g. guests on the same hypervisor; and it should
be different for unrelated cache locations, e.g. different hypervisors
and stand-alone machines.

View file

@ -13,8 +13,8 @@ NOTE: NUT does not currently provide proper graphical configuration tools.
However, there is now support for linkdoc:developer-guide[Augeas,augeas_user],
which will enable the easier creation of configuration tools.
Moreover, linkman:nut-scanner[8] is available to discover supported devices
(USB, SNMP, Eaton XML/HTTP and IPMI) and NUT servers (using Avahi or the classic
connection method).
(USB, SNMP, Eaton XML/HTTP and IPMI) and NUT servers (using Avahi or the
classic connection method).
Details about the configuration files
-------------------------------------
@ -104,7 +104,7 @@ quotes spanning multiple lines.
Basic configuration
-------------------
This chapter describe the base configuration to establish communication with
This chapter describes the base configuration to establish communication with
the device.
This will be sufficient for PDU. But for UPS and SCD, you will also need to
@ -112,21 +112,35 @@ configure <<UPS_shutdown,automatic shutdowns for low battery events>>.
image:images/simple.png[]
On operating systems with service management frameworks (such as Linux
systemd and Solaris/illumos SMF), the life-cycle of driver, data server
and monitoring client daemons is managed respectively by `nut-driver`
(multi-instance service), `nut-server` and `nut-monitor` services.
These are in turn wrapped by an "umbrella" service (or systemd "target")
conveniently called `nut` which allows to easily start or stop all those
of the bundled services, which are enabled on a particular deployment.
[[Driver_configuration]]
Driver configuration
~~~~~~~~~~~~~~~~~~~~
Create one section per UPS in /usr/local/ups/etc/ups.conf
Create one section per UPS in 'ups.conf'
To find out which driver to use, check the <<HCL,Hardware Compatibility List>>,
or data/driver.list.
NOTE: The default path for a source installation is `/usr/local/ups/etc`,
while packaged installation will vary.
For example, `/etc/nut` is used on Debian and derivatives,
while `/etc/ups` or `/etc/upsd` is used on RedHat and derivatives.
To find out which driver to use, check the
<<HCL,Hardware Compatibility List>>,
or `data/driver.list(.in)` source file.
Once you have picked a driver, create a section for your UPS in
ups.conf. You must supply values for "driver" and "port".
'ups.conf'. You must supply values at least for "driver" and "port".
Some drivers may require other flags or settings. The "desc" value
is optional, but is recommended to provide a better description of
what your UPS is supporting.
what useful load your UPS is feeding.
A typical device without any extra settings looks like this:
@ -135,19 +149,29 @@ A typical device without any extra settings looks like this:
port = /dev/ttyS1
desc = "Workstation"
NOTE: USB drivers (usbhid-ups, bcmxcp_usb, tripplite_usb, blazer_usb and
richcomm_usb) are special cases and ignore the 'port' value.
[NOTE]
======
USB drivers (such as `usbhid-ups` for non-SHUT mode, `nutdrv_qx` for
non-serial mode, `bcmxcp_usb`, `tripplite_usb`, `blazer_usb`, `riello_usb`
and `richcomm_usb`) are special cases and ignore the 'port' value.
You must still set this value, but it does not matter what you set
it to; a common and good practice is to set 'port' to *auto*, but you can
put whatever you like. If you only own one UBS UPS, the driver will
find it automatically. If you own more than one, refer to the driver's
manual page for more information on matching a specific device.
it to; a common and good practice is to set 'port' to *auto*, but you
can put whatever you like.
If you only own one USB UPS, the driver will find it automatically.
If you own more than one, refer to the driver's manual page for more
information on matching a specific device.
======
References: linkman:ups.conf[5],
linkman:nutupsdrv[8],
linkman:bcmxcp_usb[8],
linkman:blazer[8],
linkman:nutdrv_qx[8],
linkman:richcomm_usb[8],
linkman:riello_usb[8],
linkman:tripplite_usb[8],
linkman:usbhid-ups[8]
@ -156,16 +180,17 @@ linkman:usbhid-ups[8]
Starting the driver(s)
~~~~~~~~~~~~~~~~~~~~~~
Start the driver(s) for your hardware:
Generally, you can just start the driver(s) for your hardware (all sections
defined in 'ups.conf') using the following command:
/usr/local/ups/sbin/upsdrvctl start
upsdrvctl start
Make sure the driver doesn't report any errors. It should show a
few details about the hardware and then enter the background. You
should get back to the command prompt a few seconds later. For
reference, a successful start of the `usbhid-ups` driver looks like this:
# /usr/local/ups/sbin/upsdrvctl start
# upsdrvctl start
Network UPS Tools - Generic HID driver 0.34 (2.4.1)
USB communication driver 0.31
Using subdriver: MGE HID 1.12
@ -173,29 +198,96 @@ reference, a successful start of the `usbhid-ups` driver looks like this:
If the driver doesn't start cleanly, make sure you have picked the
right one for your hardware. You might need to try other drivers
by changing the "driver=" value in ups.conf.
by changing the "driver=" value in 'ups.conf'.
Be sure to check the driver's man page to see if it needs any extra
settings in `ups.conf` to detect your hardware.
settings in 'ups.conf' to detect your hardware.
If it says `can't bind /var/state/ups/...` or similar, then your
state path probably isn't writable by the driver. Check the
<<StatePath,permissions and mode on that directory>>.
<<StatePath,permissions and mode on that directory>> vs. the
user account your driver starts as.
After making changes, try the <<Ownership, Ownership and permissions>> step again.
After making changes, try the <<Ownership, Ownership and permissions>>
step again.
References: man pages: linkman:nutupsdrv[8], linkman:upsdrvctl[8]
Driver(s) as a service
~~~~~~~~~~~~~~~~~~~~~~
On operating systems with init-scripts managing life-cycle of the operating
environment, the `upsdrvctl` program is also commonly used in those scripts.
It has a few downsides, such as that if the device was not accessible during
OS startup and the driver connection timed out, it would remain not-started
until an administrator (or some other script) "kicks" the driver to retry
startup. Also, startup of the `upsd` data server daemon and its clients
like `upsmon` is delayed until all the NUT drivers complete their startup
(or time out trying).
This can be a big issue on systems which monitor multiple devices, such as
big servers with multiple power sources, or administrative workstations
which monitor a datacenter full of UPSes.
For this reason, NUT starting with version 2.8.0 supports startup of its
drivers as independent instances of a `nut-driver` service under the Linux
systemd and Solaris/illumos SMF service-management frameworks (corresponding
files and scripts may be not pre-installed in packaging for other systems).
Such service instances have their own and independent life-cycle, including
parallel driver start and stop processing, and retries of startup in case of
failure as implemented by the service framework in the OS. The Linux systemd
solution also includes a `nut-driver.target` as a checkpoint that all defined
drivers have indeed started up (as well as being a singular way to enable or
disable startup of drivers).
In both cases, a service named `nut-driver-enumerator` is registered, and
when it is (re-)started it scans the currently defined device sections in
'ups.conf' and the currently defined instances of `nut-driver` service,
and brings them in sync (adding or removing service instances), and if
there were changes -- it restarts the corresponding drivers (via service
instances) as well as the data server which only reads the list of sections
at its startup. This helper service should be triggered whenever your system
(re-)starts the `nut-server` service, so that it runs against an up-to-date
list of NUT driver processes.
A service-oriented solution also allows to consider that different drivers
have different dependencies -- such as that networked drivers should begin
startup after IP addresses have been assigned, while directly-connected
devices might need nothing beside a mounted filesystem (or an activated
USB stack service or device rule, in case of Linux). Likewise, systems
administrators can define further local dependencies between services and
their instances as needed on particular deployments.
This solution also adds the `upsdrvsvcctl` script to manage NUT drivers as
system service instances, whose CLI mimics that of `upsdrvctl` program.
One addition is the `resync` argument to trigger `nut-driver-enumerator`,
another is a `list` argument to display current mappings of service
instances to NUT driver sections. Also, original tool's arguments such
as the `-u` (user to run the driver as) or `-D` (debug of the driver)
do not make sense in the service context -- the accounts to use and
other arguments to the driver process are part of service setup (and
an administrator can manage it there).
Note that while this solution tries to register service instances with same
names as NUT configuration sections for the devices, this can not always be
possible due to constraints such as syntax supported by a particular service
management framework. In this case, the enumerator falls back to MD5 hashes
of such section names, and the `upsdrvsvcctl` script supports this to map
the user-friendly NUT configuration section names to actual service names
that it would manage.
References: man pages: linkman:nutupsdrv[8], linkman:upsdrvctl[8],
linkman:upsdrvsvcctl[8]
Data server configuration (upsd)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Configure upsd, which serves data from the drivers to the clients.
Configure `upsd`, which serves data from the drivers to the clients.
First, edit upsd.conf to allow access to your client systems. By
default, upsd will only listen to localhost port 3493/tcp. If you want
First, edit 'upsd.conf' to allow access to your client systems. By
default, `upsd` will only listen to `localhost` port 3493/tcp. If you want
to connect to it from other machines, you must specify each interface you
want upsd to listen on for connections, optionally with a port number.
want `upsd` to listen on for connections, optionally with a port number.
LISTEN 127.0.0.1 3493
LISTEN ::1 3493
@ -203,15 +295,15 @@ want upsd to listen on for connections, optionally with a port number.
NOTE: Refer to the NUT user manual <<NUT_Security,security chapter>> for
information on how to access and secure upsd clients connections.
Next, create upsd.users. For now, this can be an empty file.
Next, create 'upsd.users'. For now, this can be an empty file.
You can come back and add more to it later when it's time to
configure upsmon or run one of the management tools.
configure `upsmon` or run one of the management tools.
Do not make either file world-readable, since they both hold
access control data and passwords. They just need to be readable by
the user you created in the preparation process.
The suggested configuration is to chown it to root, chgrp it to the
The suggested configuration is to `chown` it to `root`, `chgrp` it to the
group you created, then make it readable by the group.
chown root:nut upsd.conf upsd.users
@ -227,26 +319,36 @@ Starting the data server
Start the network data server:
/usr/local/ups/sbin/upsd
upsd
Make sure it is able to connect to the driver(s) on your system.
A successful run looks like this:
# /usr/local/ups/sbin/upsd
# upsd
Network UPS Tools upsd 2.4.1
listening on 127.0.0.1 port 3493
listening on ::1 port 3493
Connected to UPS [eaton]: usbhid-ups-eaton
upsd prints dots while it waits for the driver to respond. Your
`upsd` prints dots while it waits for the driver to respond. Your
system may print more or less depending on how many drivers you
have and how fast they are.
NOTE: if upsd says that it can't connect to a UPS or that the data
is stale, then your ups.conf is not configured correctly, or you
NOTE: If `upsd` says that it can't connect to a UPS or that the data
is stale, then your 'ups.conf' is not configured correctly, or you
have a driver that isn't working properly. You must fix this before
going on to the next step.
NOTE: Normally `upsd` requires that at least one driver section is
defined in the 'ups.conf' file, and refuses to start otherwise.
If you intentionally do not have any driver sections defined (yet)
but still want the data server to run, respond and report zero devices
(e.g. on an automatically managed monitoring deployment), you can enable
the `ALLOW_NO_DEVICE true` option in the 'upsd.conf' file.
On operating systems with service management frameworks, the data server
life-cycle is managed by `nut-server` service.
Reference: man page: linkman:upsd[8]
Check the UPS data
@ -256,15 +358,16 @@ Status data
^^^^^^^^^^^
Make sure that the UPS is providing good status data.
You can use the `upsc` command-line client for this:
/usr/local/ups/bin/upsc myupsname@localhost ups.status
upsc myupsname@localhost ups.status
You should see just one line in response:
OL
OL means your system is running on line power. If it says something
else (like OB - on battery, or LB - low battery), your driver was
`OL` means your system is running on line power. If it says something
else (like `OB` -- on battery, or `LB` -- low battery), your driver was
probably misconfigured during the <<Driver_configuration, Driver configuration>>
step. If you reconfigure the driver, use `upsdrvctl stop` to stop it, then
start it again as shown in the <<Starting_drivers, Starting driver(s)>> step.
@ -277,11 +380,11 @@ All data
Look at all of the status data which is being monitored.
/usr/local/ups/bin/upsc myupsname@localhost
upsc myupsname@localhost
What happens now depends on the kind of device and driver you have.
In the list, you should see ups.status with the same value you got
above. A sample run on a UPS (Eaton Ellipse MAX 1100) looks like this:
In the list, you should see `ups.status` with the same value you got
above. A sample run on an UPS (Eaton Ellipse MAX 1100) looks like this:
battery.charge: 100
battery.charge.low: 20
@ -337,8 +440,15 @@ Startup scripts
NOTE: This step is not necessary if you installed from packages.
Edit your startup scripts, and make sure upsdrvctl and upsd are run every time
your system starts.
Edit your startup scripts, and make sure `upsdrvctl` and `upsd` are run
every time your system starts. In newer versions of NUT, you may have a
'nut.conf' file which sets the `MODE` variable for bundled init-scripts,
to facilitate enabling of certain features in the specific end-user
deployments.
If you installed from source, check the `scripts` directory for reference
init-scripts, as well as systemd or SMF service methods and manifests.
[[UPS_shutdown]]
Configuring automatic shutdowns for low battery events
@ -356,59 +466,95 @@ Shutdown design
When your UPS batteries get low, the operating system needs to be brought
down cleanly. Also, the UPS load should be turned off so that all devices
that are attached to it are forcibly rebooted.
that are attached to it are forcibly rebooted, and subsequently start in
the predictable order and state suitable for your data center.
Here are the steps that occur when a critical power event happens:
Here are the steps that occur when a critical power event happens,
for the simpler case of one UPS device feeding one or several systems:
1. The UPS goes on battery
2. The UPS reaches low battery (a "critical" UPS), that is to say
upsc displays:
2. The UPS reaches low battery (a "critical" UPS), that is to say,
`upsc` displays:
+
ups.status: OB LB
+
The exact behavior depends on the specific device, and is related to:
The exact behavior depends on the specific device, and is related to
such settings and readings as:
- battery.charge and battery.charge.low
- battery.runtime and battery.runtime.low
- `battery.charge` and `battery.charge.low`
- `battery.runtime` and `battery.runtime.low`
3. The upsmon master notices and sets "FSD" - the "forced shutdown"
flag to tell all slave systems that it will soon power down the load.
3. The `upsmon` primary notices the "critical UPS" situation and sets
"FSD" -- the "forced shutdown" flag to tell all secondary systems
that it will soon power down the load.
+
(If you have no slaves, skip to step 6)
[WARNING]
=========
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
intend to go all the way -- shut down all the servers gracefully,
and power down the UPS.
4. upsmon slave systems see "FSD" and:
Keep in mind that some UPS devices and corresponding drivers would
latch the "FSD" 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.
=========
+
(If you have no secondary systems, skip to step 6)
- generate a NOTIFY_SHUTDOWN event
- wait FINALDELAY seconds - typically 5
- call their SHUTDOWNCMD
- disconnect from upsd
4. `upsmon` secondary systems see "FSD" and:
5. The upsmon master system waits up to HOSTSYNC seconds (typically 15)
for the slaves to disconnect from upsd. If any are connected after
this time, upsmon stops waiting and proceeds with the shutdown
process.
- generate a `NOTIFY_SHUTDOWN` event
- wait `FINALDELAY` seconds -- typically `5`
- call their `SHUTDOWNCMD`
- disconnect from `upsd`
6. The upsmon master:
5. The `upsmon` primary system waits up to `HOSTSYNC` seconds (typically `15`)
for the secondary systems to disconnect from `upsd`. If any are still
connected after this time, `upsmon` primary stops waiting and proceeds
with the shutdown process.
- generates a NOTIFY_SHUTDOWN event
- waits FINALDELAY seconds - typically 5
- creates the POWERDOWNFLAG file - usually /etc/killpower
- calls the SHUTDOWNCMD
6. The `upsmon` primary:
7. On most systems, init takes over, kills your processes, syncs and
- generates a `NOTIFY_SHUTDOWN` event
- waits `FINALDELAY` seconds -- typically `5`
- creates the `POWERDOWNFLAG` file in its local filesystem --
usually `/etc/killpower`
- calls the `SHUTDOWNCMD`
7. On most systems, `init` takes over, kills your processes, syncs and
unmounts some filesystems, and remounts some read-only.
8. init then runs your shutdown script. This checks for the
POWERDOWNFLAG, finds it, and tells the UPS driver(s) to power off
the load.
8. `init` then runs your shutdown script. This checks for the
`POWERDOWNFLAG`, finds it, and tells the UPS driver(s) to power off
the load by sending commands to the connected UPS device(s) they manage.
9. The system loses power.
9. All the systems lose power.
10. Time passes. The power returns, and the UPS switches back on.
11. All systems reboot and go back to work.
///////////////////////////////////
https://github.com/networkupstools/nut/issues/1370
TODO: Check other docs and code to spell out expected behavior with
multiple UPS devices (when not all of them go critical or even on battery)
and servers with multiple inputs.
Does the `upsmon` primary system power-cycle a "critical" UPS if that
is not the only one feeding it, so it is not shutting down now?
///////////////////////////////////
How you set it up
~~~~~~~~~~~~~~~~~
@ -417,42 +563,48 @@ How you set it up
NUT user creation
^^^^^^^^^^^^^^^^^
Create a upsd user for upsmon to use while monitoring this UPS.
Create a `upsd` user for `upsmon` to use while monitoring this UPS.
Edit upsd.users and create a new section. upsmon will connect
to upsd and use this user name (in brackets) and password to
authenticate. This example is for a user called "monuser":
Edit 'upsd.users' and create a new section. The `upsmon` will connect
to `upsd` and use these user name (in brackets) and password to
authenticate (as specified in its configuration via `MONITOR` line).
This example is for defining a user called "monuser":
[monuser]
password = mypass
upsmon master
# or upsmon slave
upsmon primary
# or upsmon secondary
References: linkman:upsd[8], linkman:upsd.users[5]
Reloading the data server
^^^^^^^^^^^^^^^^^^^^^^^^^
Reload upsd. Depending on your configuration, you may be able to
do this without stopping upsd:
Reload `upsd`. Depending on your configuration, you may be able to
do this without stopping the `upsd` daemon process:
/usr/local/ups/sbin/upsd -c reload
upsd -c reload
If that doesn't work (check the syslog), just restart it:
/usr/local/ups/sbin/upsd -c stop
/usr/local/ups/sbin/upsd
upsd -c stop
upsd
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.
For systems with integrated service management (Linux systemd,
illumos/Solaris SMF) their corresponding `reload` or `refresh`
service actions should handle this as well.
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.
Power Off flag file
^^^^^^^^^^^^^^^^^^^
Set the POWERDOWNFLAG location for upsmon.
Set the `POWERDOWNFLAG` location for `upsmon`.
In upsmon.conf, add a POWERDOWNFLAG directive with a filename.
upsmon will create this file when the UPS needs to be powered off
In 'upsmon.conf', add a `POWERDOWNFLAG` directive with a filename.
The `upsmon` will create this file when the UPS needs to be powered off
during a power failure when low battery is reached.
We will test for the presence of this file in a later step.
@ -465,68 +617,79 @@ linkman:upsmon.conf[5]
Securing upsmon.conf
^^^^^^^^^^^^^^^^^^^^
The recommended setting is to have it owned by root:nut, then make it readable
by the group and not world. This file contains passwords that could be used by
an attacker to start a shutdown, so keep it secure.
The recommended setting is to have it owned by `root:nut`, then make it
readable by the group and not by the world. This file contains passwords
that could be used by an attacker to start a shutdown, so keep it secure.
chown root:nut upsmon.conf
chmod 0640 upsmon.conf
This step has been placed early in the process so you secure this file before
adding sensitive data in the next step.
This step has been placed early in the process so you secure this file
before adding sensitive data in the next step.
Create a MONITOR directive for upsmon
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Edit upsmon.conf and create a MONITOR line with the UPS definition
(<upsname>@<hostname>), username and password from the <<NUT_user_creation, NUT user creation>>
step, and the master or slave setting.
Edit 'upsmon.conf' and create a `MONITOR` line with the UPS definition
(<upsname>@<hostname>), username and password from the
<<NUT_user_creation, NUT user creation>> step, and the
"primary" or "secondary" setting.
If it's the master (i.e., it's connected to this UPS directly):
If this system is the UPS manager (i.e. it's connected to this UPS directly
and can manage it using a suitable NUT driver), its `upsmon` is the primary:
MONITOR myupsname@mybox 1 monuser mypass master
MONITOR myupsname@mybox 1 monuser mypass primary
If it's just monitoring this UPS over the network, and some other system is the
master:
If it's just monitoring this UPS over the network, and some other
system is the primary, then this one is a secondary:
MONITOR myupsname@mybox 1 monuser mypass slave
MONITOR myupsname@mybox 1 monuser mypass secondary
The number "1" here is the power value. This should always be set to 1 unless
you have a very special (read: expensive) system with redundant power supplies.
In such cases, refer to the User Manual:
The number `1` here is the "power value". This should always be set
to 1, unless you have a very special (read: expensive) system with
redundant power supplies. In such cases, refer to the User Manual:
- <<BigServers,typical setups for big servers>>,
- <<DataRoom,typical setups for data rooms>>.
Note that the "power value" may also be 0 for a monitoring (administrative)
system which only observes the remote UPS status but is not impacted by its
power events, and so does not shut down when the UPS does.
References: linkman:upsmon[8], linkman:upsmon.conf[5]
Define a SHUTDOWNCMD for upsmon
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Still in upsmon.conf, add a directive that tells upsmon how to shut down your
system. This example seems to work on most systems:
Still in 'upsmon.conf', add a directive that tells `upsmon` how to
shut down your system. This example seems to work on most systems:
SHUTDOWNCMD "/sbin/shutdown -h +0"
Notice the presence of "quotes" here to keep it together.
If your system has special needs, you may want to set this to a script which
does local shutdown tasks before calling init.
If your system has special needs (e.g. system-provided shutdown handler
is ungracefully time constrained), you may want to set this to a script
which does customized local shutdown tasks before calling `init` or
`shutdown` programs to handle the system side of this operation.
Start upsmon
^^^^^^^^^^^^
/usr/local/ups/sbin/upsmon
upsmon
If it complains about something, then check your configuration.
On operating systems with service management frameworks, the monitoring client
life-cycle is managed by `nut-monitor` service.
Checking upsmon
^^^^^^^^^^^^^^^
Look for messages in the syslog to indicate success. It should look something
like this:
Look for messages in the `syslog` to indicate success.
It should look something like this:
May 29 01:11:27 mybox upsmon[102]: Startup successful
May 29 01:11:28 mybox upsd[100]: Client monuser@192.168.50.1
@ -543,10 +706,12 @@ NOTE: This step is not need if you installed from packages.
Edit your startup scripts, and add a call to `upsmon`.
Make sure `upsmon` starts when your system comes up. Do it after `upsdrvctl`
and `upsd`, or it will complain about not being able to contact the server.
Make sure `upsmon` starts when your system comes up.
On systems with `upsmon` primary (also running the data server),
do it after `upsdrvctl` and `upsd`, or it will complain about not
being able to contact the server.
You may delete the POWERDOWNFLAG in the startup scripts, but it is not
You may delete the `POWERDOWNFLAG` in the startup scripts, but it is not
necessary. `upsmon` will clear that file for you when it starts.
NOTE: Init script examples are provide in the 'scripts' directory of
@ -560,16 +725,17 @@ NOTE: This step is not need if you installed from packages.
Edit your shutdown scripts, and add `upsdrvctl shutdown`.
You should configure your system to power down the UPS after the filesystems are
remounted read-only. Have it look for the presence of the POWERDOWNFLAG (from
linkman:upsmon.conf[5]), using this as an example:
You should configure your system to power down the UPS after the
filesystems are remounted read-only. Have it look for the presence
of the `POWERDOWNFLAG` (from linkman:upsmon.conf[5]), using this
as an example:
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
if (test -f /etc/killpower)
if (/sbin/upsmon -K)
then
echo "Killing the power, bye!"
/usr/local/ups/bin/upsdrvctl shutdown
/sbin/upsdrvctl shutdown
sleep 120
@ -578,18 +744,25 @@ linkman:upsmon.conf[5]), using this as an example:
# *** see also the section on power races in the FAQ! ***
fi
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
[WARNING]
================================================================================
- Be careful that upsdrvctl command will probably power off your machine.
==============================================================================
- Be careful that `upsdrvctl shutdown` command will probably power off
your machine and others fed by the UPS(es) which it manages.
Don't use it unless your system is ready to be halted by force.
If you run RAID, read the <<_raid_warning,RAID warning>> below!
- Make sure the filesystem(s) containing upsdrvctl, ups.conf and your UPS
driver(s) are mounted (possibly in read-only mode) when the system gets to this
point. Otherwise it won't be able to figure out what to do.
================================================================================
- Make sure the filesystem(s) containing `upsdrvctl`, `upsmon`,
the `POWERDOWNFLAG` file, 'ups.conf' and your UPS driver(s) are
mounted (possibly in read-only mode) when the system gets to
this point. Otherwise it won't be able to figure out what to do.
- If for some reason you can not ensure `upsmon` program is executable
at this point, your script can `(test -f /etc/killpower)` in a somewhat
non-portable manner, instead of asking `upsmon -K` for the verdict
according to its current configuration.
==============================================================================
[[Testing_shutdowns]]
@ -602,17 +775,17 @@ on your systems before leaving them unattended. A successful sequence
is one where the OS halts before the battery runs out, and the system
restarts when power returns.
The first step is to see how upsdrvctl will behave without actually turning off
power. To do so, use the '-t' argument:
The first step is to see how `upsdrvctl` will behave without actually
turning off the power. To do so, use the `-t` argument:
/usr/local/ups/bin/upsdrvctl -t shutdown
upsdrvctl -t shutdown
It will display the sequence without actually calling the drivers.
You can finally test a forced shutdown sequence (FSD) using:
/usr/local/ups/sbin/upsmon -c fsd
upsmon -c fsd
This will execute a full shutdown sequence, as presented in
<<Shutdown_design,Shutdown design>>, starting from the 3rd step.
@ -643,35 +816,38 @@ is turned off and waits for the power to return.
Once the power is back, the system reboots, pulls the snapshot back in,
and keeps going from there. If the user happened to be away when it
happened, they may return and have no idea that their system actually
shut down completely in the middle.
shut down completely in the middle (although network connections will drop).
In order for this to work, you need to shutdown NUT (UPS driver, upsd
server and upsmon client) in the suspend script and start them again in
the resume script. Don't try to keep them running. The upsd server
In order for this to work, you need to shutdown NUT (UPS driver, `upsd`
server and `upsmon` client) in the `suspend` script and start them again in
the `resume` script. Don't try to keep them running. The `upsd` server
will latch the FSD state (so it won't be usable after resuming) and so
will the upsmon client. Some drivers may work after resuming, but many
don't and some UPSs will require re-initialization, so it's best not
to keep this running either.
will the `upsmon` client. Some drivers may work after resuming, but many
don't and some UPS devices will require re-initialization, so it's best not
to keep them running either.
After stopping driver, server and client you'll have to send the UPS
the command to shutdown only if the POWERDOWNFLAG is present. Note
that most likely you'll have to allow for a grace period after sending
'upsdrvctl shutdown' since the system will still have to take a
snapshot of itself after that. Not all drivers support this, so before
going down this road, make sure that the one you're using does.
After stopping NUT driver, server and client you'll have to send the UPS
the command to shutdown only if the `POWERDOWNFLAG` is present. Note
that most likely you'll have to allow for a grace period after calling
`upsdrvctl shutdown` since the system will still have to take a
snapshot of itself after that. Not all drivers and devices support this,
so before going down this road, make sure that the one you're using does.
- see if you can query or configure settings named like `load.off.delay`,
`ups.delay.shutdown`, `offdelay` and/or `shutdown_delay`
RAID warning
~~~~~~~~~~~~
If you run any sort of RAID equipment, make sure your arrays are either halted
(if possible) or switched to "read-only" mode. Otherwise you may suffer a long
resync once the system comes back up.
If you run any sort of RAID equipment, make sure your arrays are
either halted (if possible) or switched to "read-only" mode.
Otherwise you may suffer a long resync once the system comes back up.
The kernel may not ever run its final shutdown procedure, so you must take care
of all array shutdowns in userspace before upsdrvctl runs.
The kernel may not ever run its final shutdown procedure, so you must take
care of all array shutdowns in userspace before `upsdrvctl shutdown` runs.
If you use software RAID (md) on Linux, get mdadm and try using
'mdadm --readonly' to put your arrays in a safe state. This has to
If you use software RAID (md) on Linux, get `mdadm` and try using
`mdadm --readonly` to put your arrays in a safe state. This has to
happen after your shutdown scripts have remounted the filesystems.
On hardware RAID or other kernels, you have to do some detective work. It may
@ -693,8 +869,8 @@ be configured using some general descriptions.
There are two main elements:
1. There's a UPS attached to a communication (serial, USB or network) port on
this system.
1. There's a UPS attached to a communication (serial, USB or network) port
on this system.
2. This system depends on a UPS for power.
You can play "mix and match" with those two to arrive at these descriptions
@ -704,36 +880,37 @@ for individual hosts:
- B: 2 but not 1
- C: 1 and 2
A small to medium sized data room usually has one C and a bunch of Bs.
This means that there's a system (type C) hooked to the UPS which depends
on it for power. There are also some other systems in there (type B)
A small to medium sized data room usually has one 'C' and a bunch of 'Bs'.
This means that there's a system (type 'C') hooked to the UPS which depends
on it for power. There are also some other systems in there (type 'B')
which depend on that same UPS for power, but aren't directly connected to
it.
it communications-wise.
Larger data rooms or those with multiple UPSes may have several "clusters"
of the "single C, many Bs" depending on how it's all wired.
of the "single 'C', many 'Bs'" depending on how it's all wired.
Finally, there's a special case. Type A systems are connected to a UPS's
serial port, but don't depend on it for power. This usually happens when
a UPS is physically close to a box and can reach the serial port, but
the wiring is such that it doesn't actually feed it.
Finally, there's a special case. Type 'A' systems are connected to
an UPS's communication port, but don't depend on it for power.
This usually happens when an UPS is physically close to a box and can
reach the serial port, but the power wiring is such that it doesn't
actually feed that box.
Once you identify a system's type, use this list to decide which of the
programs need to be run for monitoring:
- A: driver and upsd
- B: upsmon (as slave)
- C: driver, upsd, and upsmon (as master)
- A: driver and `upsd`
- B: `upsmon` (in secondary mode)
- C: driver, `upsd`, and `upsmon` (in primary mode, as the UPS manager)
image:images/advanced.png[]
To further complicate things, you can have a system that is hooked to
multiple UPSes, but only depends on one for power. This particular
situation makes it an "A" relative to one UPS, and a "C" relative to the
other. The software can handle this - you just have to tell it what to do.
situation makes it an `A` relative to one UPS, and a `C` relative to the
other. The software can handle this -- you just have to tell it what to do.
NOTE: NUT can also serve as a data proxy to increase the number of clients,
or share the communication load between several upsd instances.
image:images/advanced.png[]
or share the communication load between several `upsd` instances.
If you are running large server-class systems that have more than one
power feed, see the next section for information on how to handle it
@ -743,8 +920,8 @@ properly.
Typical setups for big servers with UPS redundancy
--------------------------------------------------
By using multiple MONITOR statements in upsmon.conf, you can configure an
environment where a large machine with redundant power monitors multiple
By using multiple `MONITOR` statements in 'upsmon.conf', you can configure
an environment where a large machine with redundant power monitors multiple
separate UPSes.
image:images/bigbox.png[]
@ -752,35 +929,39 @@ image:images/bigbox.png[]
Example configuration
~~~~~~~~~~~~~~~~~~~~~
For the examples in this section, we will use a server with four power supplies
installed.
For the examples in this section, we will use a server with four power
supplies installed and locally running the full NUT stack, including
`upsmon` in primary mode -- as the UPS manager.
Two UPS, 'Alpha' and 'Beta', are each driving two of the power supplies.
Two UPSes, 'Alpha' and 'Beta', are each driving two of the power supplies
(by adding up, we know about the four power supplies of the current system).
This means that either 'Alpha' *or* 'Beta' can totally shut down and the
server will be able to keep running.
The upsmon.conf configuration that reflect this is the following:
The 'upsmon.conf' configuration which reflects this is the following:
MONITOR ups-alpha@myhost 2 monuser mypass master
MONITOR ups-beta@myhost 2 monuser mypass master
MONITOR ups-alpha@myhost 2 monuser mypass primary
MONITOR ups-beta@myhost 2 monuser mypass primary
MINSUPPLIES 2
With that configuration, upsmon will only shut down when both UPS reaches
a critical (on battery + low battery) condition, since 'Alpha' and 'Beta'
provide the same power value.
With such configuration, `upsmon` on this system will only shut down when
both UPS devices reach a critical (on battery + low battery) condition,
since 'Alpha' and 'Beta' each provide the same power value.
As an added bonus, this means you can move a running server from one UPS
to another (for maintenance purpose for example) without bringing it down since
the minimum power will be provided at all times.
to another (for maintenance purpose for example) without bringing it down
since the minimum sufficient power will be provided at all times.
The MINSUPPLIES line tells upsmon that we need at least 2 power supplies
The `MINSUPPLIES` line tells `upsmon` that we need at least 2 power supplies
to be receiving power from a good UPS (on line or on battery, just not
on battery and low battery).
on battery *and* low battery).
NOTE: we could have used a 'Power Value' of 1 for both UPS, and MINSUPPLIES
set to 1 too. These values are purely arbitrary, so you are free to use your
own rules. Here, we have linked these values to the number of power supplies
that each UPS is feeding (2).
NOTE: We could have used a 'Power Value' of `1` for both UPS, and have
`MINSUPPLIES` set to `1` too. These values are purely arbitrary, so
you are free to use your own rules. Here, we have linked these values
to the number of power supplies that each UPS is feeding (2) since this
maps better to physical topology and allows to throw a third or fourth
UPS into the mix without much configuration headache.
Multiple UPS shutdowns ordering
@ -788,11 +969,11 @@ Multiple UPS shutdowns ordering
If you have multiple UPSes connected to your system, chances are that you
need to shut them down in a specific order. The goal is to shut down
everything but the one keeping upsmon alive at first, then you do that one
last.
everything but the one keeping `upsmon` alive at first, then you do that
one last.
To set the order in which your UPSes receive the shutdown commands, define
the 'sdorder' value in your ups.conf.
the `sdorder` value in your 'ups.conf' device sections.
[bigone]
driver = usbhid-ups
@ -810,11 +991,11 @@ the 'sdorder' value in your ups.conf.
sdorder = 0
The order runs from 0 to the highest number available. So, for this
configuration, the order of shutdowns would be 'misc', 'littleguy', and then
'bigone'.
configuration, the order of shutdowns would be 'misc', 'littleguy',
and then 'bigone'.
NOTE: If you have a UPS that shouldn't be shutdown when running 'upsdrvctl
shutdown', set the *sdorder* to *-1*.
NOTE: If you have a UPS that shouldn't be powered off when running
`upsdrvctl shutdown`, set its `sdorder` to `-1`.
Other redundancy configurations

848
docs/config-prereqs.txt Normal file
View file

@ -0,0 +1,848 @@
ifdef::website[]
Prerequisites for building NUT on different OSes
================================================
endif::website[]
This chapter aims to list packages with the tools needed on a freshly minimally
deployed worker to build as many targets of NUT recipes as possible, mainly
the diverse driver and documentation types.
NUT codebase generally should not depend on particular operating system or
kernel technology and version, and with the operating systems listed below
one can benefit from use of containers (jails, zones) to build and test
against numerous OS distributions on one physical or virtual machine,
e.g. to cover non-regression with older tool kits while taking advantage
of new releases.
* For Linux systems, we have notes on link:ci-farm-lxc-setup.txt[Setting
up the multi-arch Linux LXC container farm for NUT CI]
Some of the below are alternatives, e.g. compiler toolkits (gcc vs. clang)
or SSL implementations (OpenSSL vs Mozilla NSS) -- no problem installing
both, at a disk space cost.
NOTE: Some NUT branches may need additional or different software versions
that are not yet included into `master` branch dependencies, e.g. the DMF
(Dynamic Mapping Files) sub-project needs LUA 5.1.
More packages and/or system setup may be needed to actually run NUT with
all features enabled; chapters below concern just with building it.
General call to Test the ability to configure and build
-------------------------------------------------------
Check out from git, generate files and configure to tailor to your build
environment, and build some tests:
------
:; mkdir -p nut && cd nut && \
git clone https://github.com/networkupstools/nut/ -b master .
:; ./autogen.sh && \
./configure --with-doc=all --with-all --with-cgi && \
make all && make check && make spellcheck
------
You can toggle some `configure` options to check different dependency
variants, e.g. `--with-ssl=nss` vs. `--with-ssl=openssl`
For reproducible runs of various pre-sets of configuration during
development, take a look at `ci_build.sh` script and different `BUILD_TYPE`
(and other) environment variable settings that it supports. A minimal run
with it is just to call the script, e.g.:
------
:; mkdir -p nut && cd nut && \
git clone https://github.com/networkupstools/nut/ -b fightwarn .
:; ./ci_build.sh
------
[NOTE]
======
To build older releases, such as "vanilla" NUT 2.7.4 and older,
you may need to address some nuances:
* Ensure that `python` in `PATH` points to a python-2.x implementation
(`master` branch is fixed to work with python 2 and 3)
* Ensure that `bash` is your user and maybe system shell (or ensure the
generated `configure` script gets interpreted by it)
* Generally you may have better results with GNU Make newer than 3.81
than with other make implementations; however, builds are regularly
tested by CI with Sun dmake and BSD make as well, so recipes should
not expect GNU-only syntax and constructs to work
* Parallel builds should be okay in current development version and
since NUT 2.8.0 (is a bug to log and fix, if not), but they may be
failure-prone in 2.7.4 and earlier releases
======
For intensive rebuilds, `ccache` is recommended.
Build prerequisites to make NUT from scratch on various Operating Systems
-------------------------------------------------------------------------
Debian 10/11
~~~~~~~~~~~~
Being a popular baseline among Linux distributions, Debian is an
important build target. Related common operating systems include
Ubuntu and customized distros for Raspberry Pi, Proxmox, as well
as many others.
The package list below should largely apply to those as well,
however note that some well-known package names tend to differ.
A few of those are noted below.
[NOTE]
======
While Debian distros I've seen (8 to 11) provide a "libusb-dev"
for libusb-0.1 headers, the binary library package name is specifically
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.*
------
yielding e.g. "libusb-1.0-0-dev" (string name was seen with different
actual package source versions on both Debian 8 "Jessie" and
Debian 11 "Buster").
======
Debian-like package installations commonly start with an update of
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 \
valgrind \
cppcheck \
pkg-config \
gcc g++ clang
# 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
# and/or:
# :; apt-get install python3 python3.9
# You can find a list of what is (pre-)installed with:
# :; dpkg -l | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; apt-get install \
aspell aspell-en
# For other doc types (man-page, PDF, HTML) generation - massive packages (TEX, X11):
:; apt-get install \
asciidoc source-highlight python3-pygments dblatex
# For CGI graph generation - massive packages (X11):
:; apt-get install \
libgd-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 \
libcppunit-dev \
libssl-dev libnss3-dev \
augeas-tools libaugeas-dev augeas-lenses \
libusb-dev libusb-1.0-0-dev \
libi2c-dev \
libmodbus-dev \
libsnmp-dev \
libpowerman0-dev \
libfreeipmi-dev libipmimonitoring-dev \
libavahi-common-dev libavahi-core-dev libavahi-client-dev
# For libneon, see below
:; apt-get install \
lua5.1-dev
:; apt-get install \
bash dash ksh busybox
------
Alternatives that can depend on your system's other packaging choices:
------
:; apt-get install libneon27-dev
# ... or
:; apt-get install libneon27-gnutls-dev
------
Over time, Debian and Ubuntu had different packages and libraries providing
the actual methods for I2C; if your system lacks the `libi2c` (and so fails
to `./configure --with-all`), try adding the following packages:
------
:; apt-get install build-essential git-core libi2c-dev i2c-tools lm-sensors
------
For cross-builds (note that not everything supports multilib approach,
limiting standard package installations to one or another implementation;
in that case local containers each with one ARCH may be a better choice,
with `qemu-user-static` playing a role to "natively" run the other-ARCH
complete environments):
------
:; apt-get install \
gcc-multilib g++-multilib \
crossbuild-essential \
gcc-10:armhf gcc-10-base:armhf \
qemu-user-static
------
NOTE: For Jenkins agents, also need to `apt-get install openjdk-11-jdk-headless`
(technically, needs at least JRE 8+). You may have to ensure `/proc` is mounted
in the target chroot (or do this from the running container).
CentOS 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 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:
* https://docs.fedoraproject.org/en-US/epel/
* https://www.redhat.com/en/blog/whats-epel-and-how-do-i-use-it
* https://pkgs.org/download/epel-release
You may have to specify a mirror as the `baseurl` in a `/etc/yum.repos.d/...`
file (as the aged distributions become less served by mirrors), such as:
* https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/
+
------
# e.g. for CentOS7 currently:
:; yum install https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-14.noarch.rpm
# And edit /etc/yum.repos.d/epel.repo to uncomment and set the baseurl=...
# lines, and comment away the mirrorlist= lines (if yum hiccups otherwise)
------
General developer system helpers mentioned in link:ci-farm-lxc-setup.txt[]:
------
:; yum update
:; yum install \
sudo vim mc p7zip pigz pbzip2
------
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, it seems that development against libi2c/smbus is not
supported. Neither the suitable devel packages were found, nor i2c-based
drivers in distro packaging of NUT. Resolution and doc PRs are welcome.
------
:; yum install \
ccache time \
file systemd-devel \
git python perl curl \
make autoconf automake libtool-ltdl-devel libtool \
valgrind \
cppcheck \
pkgconfig \
gcc gcc-c++ clang
# NOTE: For python, you may eventually have to specify a variant like this
# (numbers depending on default or additional packages of your distro):
# :; yum install python-2.7.5
# and/or:
# :; yum install python3 python3-3.6.8
# You can find a list of what is (pre-)installed with:
# :; rpm -qa | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; yum install \
aspell aspell-en
# For other doc types (man-page, PDF, HTML) generation - massive packages (TEX, X11):
:; yum install \
asciidoc source-highlight python-pygments dblatex
# For CGI graph generation - massive packages (X11):
:; yum install \
gd-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 \
cppunit-devel \
openssl-devel nss-devel \
augeas augeas-devel \
libusb-devel libusbx-devel \
i2c-tools \
libmodbus-devel \
net-snmp-devel \
powerman-devel \
freeipmi-devel \
avahi-devel \
neon-devel
#?# 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?
# Some NUT code related to lua may be currently limited to lua-5.1
# or possibly 5.2; the former is default in CentOS 7 releases...
:; yum install \
lua-devel
:; yum install \
bash dash ksh
------
NOTE: `busybox` is not packaged for CentOS 7 release; a static binary can
be downloaded if needed. For more details, see
https://unix.stackexchange.com/questions/475584/cannot-install-busybox-on-centos
CentOS packaging for 64-bit systems delivers the directory for dispatching
compiler symlinks as `/usr/lib64/ccache`. You can set it up same way as for
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`
(technically, needs at least JRE 8+).
FreeBSD 12.2
~~~~~~~~~~~~
Note that `PATH` for builds on BSD should include `/usr/local/...`:
------
:; PATH=/usr/local/libexec/ccache:/usr/local/bin:/usr/bin:$PATH
:; export PATH
------
NOTE: You may want to reference `ccache` even before all that, as detailed
below.
------
:; pkg install \
git python perl5 curl \
gmake autoconf automake autotools libltdl libtool \
valgrind \
cppcheck \
pkgconf \
gcc clang
# NOTE: For python, you may eventually have to specify a variant like this
# (numbers depending on default or additional packages of your distro):
# :; pkg install python2 python27
# and/or:
# :; pkg install python3 python37
# You can find a list of what is (pre-)installed with:
# :; pkg info | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; pkg install \
aspell en-aspell
# For other doc types (man-page, PDF, HTML) generation - massive packages (TEX, X11):
:; pkg install \
asciidoc source-highlight textproc/py-pygments dblatex
# For CGI graph generation - massive packages (X11):
:; pkg install \
libgd
:; pkg install \
cppunit \
openssl nss \
augeas \
libmodbus \
neon \
net-snmp \
powerman \
freeipmi \
avahi
:; pkg install \
lua51
:; pkg install \
bash dash busybox ksh93
------
Recommended:
------
:; pkg install ccache
:; ccache-update-links
------
For compatibility with common setups on other operating systems, can symlink
`/usr/local/libexec/ccache` as `/usr/lib/ccache` and possibly add dash-number
suffixed symlinks to compiler tools (e.g. `gcc-10` beside `gcc10` installed
by package).
NOTE: For Jenkins agents, also need to `pkg install openjdk8` (or 11+) --
and do note its further OS configuration suggestions for special filesystem
mounts.
Due to BSD specific paths *when not using* an implementation of `pkg-config`
or `pkgconf` (so guessing of flags is left to administrator -- TBD in NUT
`m4` scripts), better use this routine to test the config/build:
----
:; ./configure --with-doc=all --with-all --with-cgi \
--without-avahi --without-powerman --without-modbus \
### CPPFLAGS="-I/usr/local/include -I/usr/include" \
### LDFLAGS="-L/usr/local/lib -L/usr/lib"
----
Note the lack of `pkg-config` also precludes `libcppunit` tests, although
they also tend to mis-compile/mis-link with GCC (while CLANG seems okay).
OpenBSD 6.4
~~~~~~~~~~~
Note that `PATH` for builds on BSD should include `/usr/local/...`:
------
:; PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
:; export PATH
------
NOTE: You may want to reference `ccache` even before all that, as detailed
below.
OpenBSD delivers many versions of numerous packages, you should specify
your pick interactively or as part of package name (e.g. `autoconf-2.69p2`).
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
------
To use the `ci_build.sh` don't forget `bash` which is not part of OpenBSD
base installation. It is not required for "legacy" builds arranged by just
`autogen.sh` and `configure` scripts.
NOTE: The OpenBSD 6.4 `install64.iso` installation includes a set of packages
that seems to exceed whatever is available on network mirrors; for example,
the CD image included `clang` program while it is not available to `pkg_add`,
at least not via http://ftp.netbsd.hu/mirrors/openbsd/6.4/packages/amd64/
mirror. The `gcc` version on CD image differed notably from that in the
networked repository (4.2.x vs 4.9.x)
------
:; pkg_add \
git python curl \
gmake autoconf automake libltdl libtool \
valgrind \
cppcheck \
pkgconf \
gcc clang
# NOTE: For python, you may eventually have to specify a variant like this
# (numbers depending on default or additional packages of your distro):
# :; yum install python-2.7.15p0
# and/or:
# :; yum install python-3.6.6p1
# although you might succeed specifying shorter names and the packager
# will offer a list of matching variants.
# NOTE: "perl" is not currently a package, but seemingly part of base OS.
# You can find a list of what is (pre-)installed with:
# :; pkg_info | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; pkg_add \
aspell
# For other doc types (man-page, PDF, HTML) generation - massive packages (TEX, X11):
:; pkg_add \
asciidoc source-highlight py-pygments dblatex \
docbook2x docbook-to-man
# For CGI graph generation - massive packages (X11):
:; pkg_add \
gd
:; pkg_add \
cppunit \
openssl nss \
augeas \
libusb1 \
neon \
net-snmp \
avahi
# Select a LUA-5.1 (or possibly 5.2?) version
:; pkg_add \
lua
:; pkg_add \
bash dash busybox 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?
------
:; pkg_add \
freeipmi
------
======
Recommended:
------
:; pkg_add ccache
:; ( mkdir -p /usr/lib/ccache && cd /usr/lib/ccache && \
for TOOL in cpp gcc g++ clang clang++ clang-cpp ; do \
ln -s ../../local/bin/ccache "$TOOL" ; \
done ; \
)
------
For compatibility with common setups on other operating systems, can add
dash-number suffixed symlinks to compiler tools (e.g. `gcc-4.2.1` beside
`gcc` installed by package) into `/usr/lib/ccache`.
NOTE: For Jenkins agents, also need to `pkg_add jre` or `pkg_add jdk`
(pick version 1.8 or 8, or 11+).
Due to BSD specific paths *when not using* an implementation of `pkg-config`
or `pkgconf` (so guessing of flags is left to administrator -- TBD in NUT
`m4` scripts), better use this routine to test the config/build:
------
:; ./configure --with-doc=all --with-all --with-cgi \
--without-avahi --without-powerman --without-modbus \
### CPPFLAGS="-I/usr/local/include -I/usr/include"
### LDFLAGS="-L/usr/local/lib -L/usr/lib"
------
Note the lack of `pkg-config` also precludes `libcppunit` tests, although
they also tend to mis-compile/mis-link with GCC (while CLANG seems okay).
NetBSD 9.2
~~~~~~~~~~
Instructions below assume that `pkgin` tool (pkg-src component to
"install binary packages") is present on the system. Text below
was prepared with a VM where "everything" was installed from the
ISO image, including compilers and X11. It is possible that some
packages provided this way differ from those served by `pkgin`,
or on the contrary, that the list of suggested tool installation
below would not include something a bare-minimum system would
require to build NUT.
Note that `PATH` for builds on NetBSD should include `local` and
`pkg`; the default after installation of the test system was:
------
:; PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/pkg/sbin:/usr/pkg/bin:/usr/X11R7/bin:/usr/local/sbin:/usr/local/bin"
:; export PATH
------
NOTE: You may want to reference `ccache` even before all that,
as detailed below:
------
:; PATH="/usr/lib/ccache:$PATH"
:; export PATH
------
To use the `ci_build.sh` don't forget `bash` which is not part of OpenBSD
base installation. It is not required for "legacy" builds arranged by just
`autogen.sh` and `configure` scripts.
------
:; pkgin install \
git python27 python39 perl curl \
make gmake autoconf automake libltdl libtool \
cppcheck \
pkgconf \
gcc7 clang
;; ( cd /usr/pkg/bin && ( ln -fs python2.7 python2 ; ln -fs python3.9 python3 ) )
# You can find a list of what is (pre-)installed with:
# :; pkgin list | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; pkgin install \
aspell aspell-en
# For man-page doc types, footprint on this platform is moderate:
:; pkgin install \
asciidoc
# For other doc types (PDF, HTML) generation - massive packages (TEX, X11):
:; pkgin install \
source-highlight py39-pygments dblatex
# For CGI graph generation - massive packages (X11):
:; pkgin install \
gd openmp
:; pkgin install \
cppunit \
openssl nss \
augeas \
libusb libusb1 \
neon \
net-snmp \
avahi
# Select a LUA-5.1 (or possibly 5.2?) version
:; pkgin install \
lua51
:; pkgin install \
bash dash ast-ksh oksh
------
[NOTE]
======
(TBD) On NetBSD 9.2 this package complains that it requires
OS ABI 9.0, or that `CHECK_OSABI=no` is set in `pkg_install.conf`.
Such file was not found in the test system...
------
:; pkgin install \
openipmi
------
======
Recommended: For compatibility with common setups on other operating
systems, can add dash-number suffixed symlinks to compiler tools (e.g.
`gcc-7` beside the `gcc` installed by package) near the original
binaries and into `/usr/lib/ccache`:
------
:; ( cd /usr/bin && for TOOL in cpp gcc g++ ; do \
ln -s "$TOOL" "$TOOL-7" ; \
done )
# Note that the one delivered binary is `clang-13` and many (unnumbered)
# symlinks to it. For NUT CI style of support for builds with many
# compilers, complete the known numbers:
:; ( cd /usr/pkg/bin && for TOOL in clang-cpp clang++ ; do \
ln -s clang-13 "$TOOL-13" ; \
done )
:; pkgin install ccache
:; ( mkdir -p /usr/lib/ccache && cd /usr/lib/ccache && \
for TOOL in cpp gcc g++ clang ; do \
for VER in "" "-7" ; do \
ln -s ../../pkg/bin/ccache "$TOOL$VER" ; \
done ; \
done ; \
for TOOL in clang clang++ clang-cpp ; do \
for VER in "" "-13" ; do \
ln -s ../../pkg/bin/ccache "$TOOL$VER" ; \
done ; \
done ; \
)
------
NOTE: For Jenkins agents, also need to `pkgin install openjdk11` (will be
in `JAVA_HOME=/usr/pkg/java/openjdk11`).
OpenIndiana 2021.10
~~~~~~~~~~~~~~~~~~~
Note that due to IPS and `pkg(5)`, a version of python is part of baseline
illumos-based OS; this may not be the case on some other illumos distributions
which do not use IPS however. Currently they use python 3.7 or newer.
To build older NUT releases (2.7.4 and before), you may need to explicitly
`pkg install python-27`.
Typical tooling would include:
------
:; pkg install \
git curl wget \
gnu-make autoconf automake libltdl libtool \
valgrind \
pkg-config \
gnu-binutils developer/linker
# NOTE: For python, some suitable version should be available since `pkg(5)`
# tool is written in it. Similarly, many system tools are written in perl
# so some version should be installed. You may specify additional variants
# like this (numbers depending on default or additional packages of your
# distro; recommended to group `pkg` calls with many packages at once to
# save processing time for calculating a build strategy):
# :; pkg install runtime/python-27
# and/or:
# :; pkg install runtime/python-37 runtime/python-35 runtime/python-39
# Similarly for perl variants, e.g.:
# :; pkg install runtime/perl-522 runtime/perl-524 runtime/perl-534
# You can find a list of what is available in remote repositories with:
# :; pkg info -r | grep -Ei 'perl|python'
# For spell-checking, highly recommended if you would propose pull requests:
:; pkg install \
aspell text/aspell/en
# For other doc types (man-page, PDF, HTML) generation - massive packages (TEX, X11):
:; pkg install \
asciidoc libxslt \
docbook/dtds docbook/dsssl docbook/xsl docbook docbook/sgml-common pygments-39 \
graphviz expect graphviz-tcl
# For CGI graph generation - massive packages (X11):
:; pkg install \
gd
:; pkg install \
openssl library/mozilla-nss \
library/augeas python/augeas \
libusb-1 libusbugen system/library/usb/libusb system/header/header-usb driver/usb/ugen \
libmodbus \
neon \
net-snmp \
powerman \
freeipmi \
avahi
:; pkg install \
lua
:; pkg install \
dash bash shell/ksh93
### Maybe
:; pkg install \
gnu-coreutils
### Maybe - after it gets fixed for GCC builds/linkage
:; pkg install \
cppunit
------
For extra compiler coverage, we can install a large selection of versions,
although to meet NUT CI farm expectations we also need to expose "numbered"
filenames, as automated below:
------
:; pkg install \
gcc-48 gcc-49 gcc-5 gcc-6 gcc-7 gcc-9 gcc-10 gcc-11 \
clang-80 clang-90 \
ccache
# As of this writing, clang-13 refused to link (claiming issues with
# --fuse-ld which was never specified) on OI; maybe later it will:
:; pkg install \
developer/clang-13 runtime/clang-13
# Get clang-cpp-X visible in standard PATH (for CI to reference the right one),
# and make sure other frontends are exposed with versions (not all OI distro
# releases have such symlinks packaged right), e.g.:
:; (cd /usr/bin && for X in 8 9 13 ; do for T in "" "++" "-cpp"; do \
ln -fs "../clang/$X.0/bin/clang$T" "clang${T}-${X}" ; \
done; done)
# If /usr/lib/ccache/ symlinks to compilers do not appear after package
# installation, or if you had to add links like above, call the service:
:; svcadm restart ccache-update-symlinks
------
We can even include a `gcc-4.4.4-il` version (used to build the illumos OS
ecosystems, at least until recently, which is a viable example of an old
GCC baseline); but note that so far it conflicts with `libgd` builds at
`./configure --with-cgi` stage (its binaries require newer ecosystem):
------
:; pkg install \
illumos-gcc@4.4.4
# Make it visible in standard PATH
:; (cd /usr/bin && for T in gcc g++ cpp ; do \
ln -s ../../opt/gcc/4.4.4/bin/$T $T-4.4.4 ; \
done)
# If /usr/lib/ccache/ symlinks to these do not appear, call the service:
:; svcadm restart ccache-update-symlinks
------
OI currently also does not build `cppunit`-based tests well, at least
not with GCC (they segfault at run-time with `ostream` issues); a CLANG
build works for that however.
It also lacks out-of-the-box Tex suite and `dblatex` in particular, which
`asciidoc` needs to build PDF documents. It may be possible to add these
from third-party repositories (e.g. SFE) and/or build from sources.
No pre-packaged `cppcheck` was found, either.
NOTE: For Jenkins agents, also need to `pkg install developer/java/openjdk8`
(or `pkg install runtime/java/openjdk11` for JRE 11 -- currently the OS does
not offer in-distro JDK version 11+).
OmniOS CE (as of release 151036)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Being a minimal-footprint system, OmniOS CE provides very few packages out
of the box. There are additional repositories supported by the project, as
well as third-party repositories such as SFE. For some dependencies, it may
happen that you would need to roll and install your own builds in accordance
with that project's design goals.
Note you may need not just the "Core" IPS package publisher, but also the
"Extra" one. See OmniOS CE web site for setup details.
------
:; pkg install \
developer/build/autoconf developer/build/automake developer/build/libtool \
build-essential ccache git developer/pkg-config \
runtime/perl \
asciidoc \
libgd
:; pkg install \
net-snmp
# NOTE: For python, some suitable version should be available since `pkg(5)`
# tool is written in it. You may specify an additional variant like this
# (numbers depending on default or additional packages of your distro):
# :; pkg install runtime/python-37
# You can find a list of what is available in remote repositories with:
# :; pkg info -r | grep -Ei 'perl|python'
------
OmniOS lacks a pre-packaged libusb, however the binary build from contemporary
OpenIndiana can be used (copy the header files and the library+symlinks for
all architectures you would need).
You may need to set up `ccache` with the same `/usr/lib/ccache` dir used
in other OS recipes. Assuming your Build Essentials pulled GCC 9 version,
and ccache is under `/opt/ooce` namespace, that would be like:
------
:; mkdir -p /usr/lib/ccache
:; cd /usr/lib/ccache
:; ln -fs ../../../opt/ooce/bin/ccache gcc
:; ln -fs ../../../opt/ooce/bin/ccache g++
:; ln -fs ../../../opt/ooce/bin/ccache gcpp
:; ln -fs ../../../opt/ooce/bin/ccache gcc-9
:; ln -fs ../../../opt/ooce/bin/ccache g++-9
:; ln -fs ../../../opt/ooce/bin/ccache gcpp-9
------
Given that many of the dependencies can get installed into that namespace,
you may have to specify where `pkg-config` will look for them (note that
library and binary paths can be architecture bitness-dependent):
------
:; ./configure PKG_CONFIG_PATH="/opt/ooce/lib/amd64/pkgconfig" --with-cgi
------
Note also that the minimal footprint nature of OmniOS CE precludes building
any large scope easily, so avoid docs and "all drivers" unless you provide
whatever they need to happen.

View file

@ -3,96 +3,229 @@ Configure options
=================
endif::website[]
There are a few options that can be given to configure to tweak compiles.
See also "./configure --help" for a current and complete listing.
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.
Driver selection
----------------
Serial drivers
~~~~~~~~~~~~~~
--with-serial
USB drivers
~~~~~~~~~~~
Build and install the serial drivers (default: yes)
--with-usb
Build and install the USB drivers (default: auto-detect)
Note that you need to install the libusb development package or files.
Note that you need to install the libusb development package or files,
and that both libusb 0.1 and 1.0 are supported. In case both are
available, libusb 1.0 takes precedence, and will be used by default.
It is however possible to override this default choice by explicitly
calling `--with-usb=libusb-0.1` or `--with-usb=libusb-1.0`.
If you do specify the version to use (or `yes` for auto-detection),
this option would fail if requested (or any) libusb version was not
found. The default `auto` value would not fail in such case.
SNMP drivers
~~~~~~~~~~~~
--with-snmp
Build and install the SNMP drivers (default: auto-detect)
Note that you need to install libsnmp development package or files.
--with-net-snmp-config
In addition to the `--with-snmp` option above, this one allows to provide
a custom program name (in `PATH`) or complete pathname to `net-snmp-config`
(may have copies named per architecture, e.g. `net-snmp-config-32` and
`net-snmp-config-64`).
This may be needed on build systems which support multiple architectures,
or in cases where your distribution names this program differently.
With a default value of `yes` it would mean preference of this program,
compared to information from `pkg-config`, if both are available.
XML drivers and features
~~~~~~~~~~~~~~~~~~~~~~~~
--with-neon
Build and install the XML drivers (default: auto-detect)
Note that you need to install neon development package or files.
LLNC CHAOS Powerman driver
~~~~~~~~~~~~~~~~~~~~~~~~~~
--with-powerman
Build and install Powerman PDU client driver (default: auto-detect)
This allows to interact with the Powerman daemon, and the numerous
Power Distribution Units (PDU) supported by the project.
Power Distribution Units (PDU) supported by the
https://github.com/chaos/powerman[powerman] project.
Note that you need to install powerman development package or files.
IPMI drivers
~~~~~~~~~~~~
--with-ipmi
--with-freeipmi
Build and install IPMI PSU driver (default: auto-detect)
This allows to monitor numerous Power Supply Units (PSU) found
on servers.
Note that you need to install freeipmi (0.8.5 or higher) development package or
files.
This allows to monitor numerous Power Supply Units (PSU) found on servers.
Note that you need to install freeipmi (0.8.5 or higher, for nut-scanner;
and 1.0.1 or higher, for nut-ipmipsu) development package or files.
I2C bus drivers
~~~~~~~~~~~~~~~
--with-linux_i2c
Build and install i2c drivers (default: auto-detect)
Note that you need to install libi2c development package or files.
Modbus drivers
~~~~~~~~~~~~~~
--with-modbus
Build and install modbus (Serial, TCP) drivers (default: auto-detect)
Note that you need to install libmodbus development package or files.
Manual selection of drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
--with-drivers=<driver>,<driver>,...
Specify exactly which driver or drivers to build and install (this
works for serial, usb, and snmp drivers, and overrides the
preceding three options).
As of the time of this writing (2010), there are 46 UPS drivers
As of the time of original writing (2010), there are 46 UPS drivers
available. Most users will only need one, a few will need two or
three, and very few people will need all of them.
To save time during the compile and disk space later on, you can
use this option to just build and install a subset of the drivers.
To select mge-shut and usbhid-ups, you'd do this:
For example, to select `mge-shut` and `usbhid-ups`, you'd do this:
--with-drivers=apcsmart,usbhid-ups
If you need to build more drivers later on, you will need to rerun
configure with a different list. To make it build all of the
drivers from scratch again, run 'make clean' before starting.
`configure` with a different list. To make it build all of the
drivers from scratch again, run `make clean` before starting.
Optional features
-----------------
CGI client interface
~~~~~~~~~~~~~~~~~~~~
--with-cgi (default: no)
Build and install the optional CGI programs, HTML files, and sample
CGI configuration files. This is not enabled by default, as they
are only useful on web servers. See data/html/README for additional
are only useful on web servers. See link:data/html/README[] for additional
information on how to set up CGI programs.
Pretty documentation and man pages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--with-doc=<output-format(s)> (default: no)
Build and install NUT documentation file(s).
The possible values are "html-single" for single page HTML, "html-chunked"
for multi pages HTML, "pdf" for a PDF file or "auto" to build all the
possible previous documentation formats.
Verbose output can be enabled using: ASCIIDOC_VERBOSE=-v make
This feature requires AsciiDoc 8.6.3 (http://www.methods.co.nz/asciidoc).
This feature requires AsciiDoc 8.6.3 or newer (see https://asciidoc.org).
The possible documentation type values are:
* `html-single` for single page HTML,
* `html-chunked` for multi-paged HTML,
* `pdf` for a PDF file, and
* `man` for the usual manpages.
Other values understood for this option are listed below:
* If the `--with-doc` argument is passed without a list, or specifies
just `=yes` or `=all`, it enables all supported formats with a `=yes`
to require them.
* An (explicit!) `--with-doc=auto` argument tries to enable all supported
formats with an `=auto` but should not fail the build if something
can not be generated.
* A `--with-doc=no` quietly skips generation of all types of documentation,
including manpages.
* `--with-doc=skip` is used to configure some of the `make distcheck*`
scenarios to re-use man page files built and distributed by the main
build and not waste time on re-generation of those.
Multiple documentation format values can be specified, separated with comma.
Each such value can be suffixed with `=yes` to require building of this one
documentation format (abort configuration if tools are missing), `=auto` to
detect and enable if we can build it on this system (and not abort if we
can not), and `=no` (or `=skip`) to explicitly skip generation of this
document format even if we do have the tools to build it.
If a document format is mentioned in the list without a suffix, then it is
treated as a `=yes` requirement.
Verbose output can be enabled using: `ASCIIDOC_VERBOSE=-v make`
Example valid formats of this flag:
* `--with-doc` without an argument, effectively same as `--with-doc=yes`
* `--with-doc=` is a valid empty list, effectively same as `--with-doc=no`
* `--with-doc=auto`
* `--with-doc=pdf,html-chunked`
* `--with-doc=man=no,pdf=auto,html-single`
Development files
~~~~~~~~~~~~~~~~~
--with-dev (default: no)
Build and install the upsclient and nutclient library and header files.
Build and install the upsclient and nutclient library and header files, to
build further projects against NUT (such as wmNUT client and many others).
Options for developers
~~~~~~~~~~~~~~~~~~~~~~
--enable-check-NIT (default: no)
Add `make check-NIT` to default activity of `make check` to run the
NUT Integration Testing suite. This is potentially dangerous (e.g. due
to port conflicts when running many such tests in same environment),
so not active by default.
--enable-maintainer-mode (default: no)
Use maintainer mode to keep `Makefile.in` and `Makefile` in sync with
ever-changing `Makefile.am` content after Git updates or editing.
--enable-cppcheck (default: no)
Activate recipes for static analysis with `cppcheck` tools (if available).
I want it all!
~~~~~~~~~~~~~~
--with-all (no default)
@ -100,42 +233,71 @@ Build and install all of the above (the serial, USB, SNMP, XML/HTTP and
PowerMan drivers, the CGI programs and HTML files, and the upsclient
library).
Networking transport security
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--with-ssl (default: auto-detect)
--with-nss (default: auto-detect)
--with-openssl (default: auto-detect)
Enable SSL support, using either Mozilla NSS or OpenSSL.
If both are present, and nothing was specified, OpenSSL support will
be preferred. Read docs/security.txt for instructions on SSL support.
be preferred.
Read link:docs/security.txt[] for instructions on SSL support.
NOTE: Currently the two implementations differ in supported features.
Networking access security
~~~~~~~~~~~~~~~~~~~~~~~~~~
--with-wrap (default: auto-detect)
Enable libwrap (tcp-wrappers) support. Refer to upsd man page for
more information.
Enable libwrap (tcp-wrappers) support.
Refer to linkman:upsd[8] man page for more information.
Networking IPv6
~~~~~~~~~~~~~~~
--with-ipv6 (default: auto-detect)
Enable IPv6 support.
AVAHI/mDNS
~~~~~~~~~~
--with-avahi (default: auto-detect)
Build and install Avahi support, to publish NUT server availability
using mDNS protocol. This requires Avahi development files for the
Core and Client parts.
LibLTDL
~~~~~~~
--with-libltdl (default: auto-detect)
Enable libltdl (Libtool dlopen abstraction) support.
This is required to build nut-scanner.
This is required to build `nut-scanner` which loads third-party libraries
dynamically, based on requested scanning options. This allows to build and
package the tool without requiring all possible dependencies to be installed
in each run-time environment.
Other configuration options
---------------------------
NUT data server port
~~~~~~~~~~~~~~~~~~~~
--with-port=PORT
Change the TCP port used by the network code. Default is 3493.
Change the TCP port used by the network code. Default is 3493
as registered with IANA.
Ancient versions of upsd used port 3305. NUT 2.0 and up use a
Ancient versions of `upsd` used port 3305. NUT 2.0 and up use a
substantially different network protocol and are not able to
communicate with anything older than the 1.4 series.
@ -143,41 +305,48 @@ If you have to monitor a mixed environment, use the last 1.4 version,
as it contains compatibility code for both the old "REQ" and the new
"GET" versions of the protocol.
Daemon user accounts
~~~~~~~~~~~~~~~~~~~~
--with-user=<username>
--with-group=<groupname>
Programs started as root will setuid() to <username> for somewhat
safer operation. You can override this with -u <user> in several
programs, including upsdrvctl (and all drivers by extension), upsd,
and upsmon. The "user" directive in ups.conf overrides this at run
Programs started as `root` will `setuid()` to `<username>` for somewhat
safer operation. You can override this with `-u <otheruser>` in several
programs, including `upsdrvctl` (and all drivers by extension), `upsd`,
and `upsmon`. The "user" directive in `ups.conf` overrides this at run
time for the drivers.
NOTE: upsmon does not totally drop root because it may need to
NOTE: `upsmon` does not totally drop `root` because it may need to
initiate a shutdown. There is always at least a stub process
remaining with root powers. The network code runs in another
remaining with `root` powers. The network code runs in another
(separate) process as the new user.
The <groupname> is used for the permissions of some files,
The `<groupname>` is used for the permissions of some files,
particularly the hotplugging rules for USB. The idea is that the
device files for any UPS devices should be readable and writable by
members of that group.
The default value for both the username and groupname is "nobody".
The default value for both the username and groupname is `nobody`
(or `nogroup` on systems that have it when `configure` script runs).
This was done since it's slightly better than staying around as
root. Running things as nobody is not a good idea, since it's a
`root`. Running things as `nobody` is not a good idea, since it's a
hack for NFS access. You should create at least one separate user
for this software.
If you use one of the --with-user and --with-group options, then
If you use one of the `--with-user` and `--with-group` options, then
you have to use the other one too.
See the INSTALL.nut document and the FAQ for more on this topic.
See the link:INSTALL.nut[] document and the FAQ for more on this topic.
Syslog facility
~~~~~~~~~~~~~~~
--with-logfacility=FACILITY
Change the facility used when writing to the log file. Read the man
page for openlog to get some idea of what's available on your system.
Default is LOG_DAEMON.
page for `openlog` to get some idea of what's available on your system.
Default is `LOG_DAEMON`.
Installation directories
@ -187,111 +356,165 @@ Installation directories
This is a fairly standard option with GNU autoconf, and it sets the
base path for most of the other install directories. The default
is /usr/local/ups, which puts everything but the state sockets in one
easy place.
is `/usr/local/ups`, which puts everything but the state sockets in one
easy place, and does not conflict with usual distribution packaging.
If you like having things to be at more of a "system" level, setting
the prefix to /usr/local or even /usr might be better.
the prefix to `/usr/local` or even `/usr` might be better.
--exec_prefix=PATH
This sets the base path for architecture dependent files. By
default, it is the same as <prefix>.
default, it is the same as `<prefix>`.
--sysconfdir=PATH
Changes the location where NUT's configuration files are stored.
By default this path is <prefix>/etc. Setting this to /etc or
/etc/ups might be useful.
By default this path is `<prefix>/etc`. Setting this to `/etc/nut` or
`/etc/ups` might be useful.
The NUT_CONFPATH environment variable overrides this at run time.
The `NUT_CONFPATH` environment variable overrides this at run time.
--bindir=PATH
--sbindir=PATH
--bindir=PATH
Where executable files will be installed. Files that are normally
executed by root (upsd, upsmon, upssched) go to sbindir, all others
to bindir. The defaults are <exec_prefix>/bin and <exec_prefix>/sbin.
executed by root (`upsd`, `upsmon`, `upssched`) go to `<sbindir>`,
all others to `<bindir>`. The defaults are `<exec_prefix>/sbin` and
`<exec_prefix>/bin` respectively.
--datadir=PATH
Change the data directory, i.e., where architecture independent
read-only data is installed. By default this is <prefix>/share,
i.e., /usr/local/ups/share. At the moment, this directory only
holds two files - the optional cmdvartab and driver.list.
--mandir=PATH
Sets the base directories for the man pages. The default is
<prefix>/man, i.e., /usr/local/ups/man.
--includedir=PATH
Sets the path for include files to be installed when `--with-dev` is
selected. For example, upsclient.h is installed here. The default
is <prefix>/include.
--libdir=PATH
Sets the installation path for libraries. This is just the
upsclient library for now. The default is <exec_prefix>/lib.
See also `--with-drvpath` below.
--with-drvpath=PATH
The UPS drivers will be installed to this path. By default they
install to "<exec_prefix>/bin", i.e., /usr/local/ups/bin.
install to `<exec_prefix>/bin`, i.e. `/usr/local/ups/bin`.
The "driverpath" global directive in the ups.conf file overrides this
You would want a location that remains mounted when most of the system
is prepared to turn off, so some distributions package NUT drivers into
`/lib/nut` or similar. See link:config-notes.txt[] detailing how to
set up system shutdown.
The `driverpath` global directive in the `ups.conf` file overrides this
at run time.
--datadir=PATH
Change the data directory, i.e., where architecture independent
read-only data is installed. By default this is `<prefix>/share`,
i.e. `/usr/local/ups/share`. At the moment, this directory only
holds two files -- the optional `cmdvartab` and `driver.list`.
--mandir=PATH
Sets the base directories for the man pages. The default is
`<prefix>/man`, i.e. `/usr/local/ups/man`.
--includedir=PATH
Sets the path for include files to be installed when `--with-dev` is
selected. For example, `upsclient.h` is installed here. The default
is `<prefix>/include`.
--libdir=PATH
Sets the installation path for libraries. Depending on the build
configuration, this can include the `libupsclient`, `libnutclient`,
`libnutclientsub`, `libnutscan` and their pkg-config metadata (see
`--with-pkgconfig-dir` option). The default is `<exec_prefix>/lib`.
--with-pkgconfig-dir=PATH
Where to install pkg-config `*.pc` files. This option only has an
effect if `--with-dev` is selected, and causes a pkg-config file to
be installed in the named location. The default is
`<exec_prefix>/pkgconfig`.
Use `--without-pkgconfig-dir` to disable this feature altogether.
--with-cgipath=PATH
The CGI programs will be installed to this path. By default, they
install to "<exec_prefix>/cgi-bin", which is usually /usr/local/ups/cgi-bin.
install to `<exec_prefix>/cgi-bin`, which is usually
`/usr/local/ups/cgi-bin`.
If you set the prefix to something like /usr, you should set the
cgipath to something else, because /usr/cgi-bin is pretty ugly and
NOTE: If you set the prefix to something like `/usr`, you should set the
`cgipath` to something else, because `/usr/cgi-bin` is pretty ugly and
non-standard.
The CGI programs are not built or installed by default. Use
"./configure --with-cgi" to request that they are built and
`./configure --with-cgi` to request that they are built and
installed.
--with-htmlpath=PATH
HTML files will be installed to this path. By default, this is
"<prefix>/html". Note that HTML files are only installed if
--with-cgi is selected.
--with-pkgconfig-dir=PATH
Where to install pkg-config *.pc files. This option only has an
effect if `--with-dev` is selected, and causes a pkg-config file to
be installed in the named location. The default is
<exec_prefix>/pkgconfig.
Use --without-pkgconfig-dir to disable this feature altogether.
`<prefix>/html`. Note that HTML files are only installed if
`--with-cgi` is selected.
--with-hotplug-dir=PATH
Where to install Linux 2.4 hotplugging rules. The default is
/etc/hotplug, if that directory exists, and not to install it
Where to install Linux 2.4 hotplugging rules. The default is to use
`/etc/hotplug`, if that directory exists, and to not install it
otherwise. Note that this installation directory is not a
subdirectory of <prefix> by default. When installing NUT as a
subdirectory of `<prefix>` by default. When installing NUT as a
non-root user, you may have to override this option.
Use --without-hotplug-dir to disable this feature altogether.
Use `--without-hotplug-dir` to disable this feature altogether.
--with-udev-dir=PATH
Where to install Linux 2.6 hotplugging rules, for kernels that have
the "udev" mechanism. The default is /etc/udev, if that directory
exists, and not to install it otherwise. Note that this
installation directory is not a subdirectory of <prefix> by
the "udev" mechanism. The default is to use `/etc/udev`, if that
directory exists, and to not install it otherwise. Note that this
installation directory is not a subdirectory of `<prefix>` by
default. When installing NUT as a non-root user, you may have to
override this option.
Use --without-udev-dir to disable this feature altogether.
Use `--without-udev-dir` to disable this feature altogether.
--with-systemdsystemunitdir=PATH
Where to install Linux systemd unit definitions. Useless and harmless
on other OSes, including Linux distributions without systemd, just adding
a little noise to configure script output.
Use `--with-systemdsystemunitdir=auto` (default) to detect the settings
using pkg-config if possible.
Use `--with-systemdsystemunitdir(=yes)` to require detection of these
settings with pkg-config, or fail configuration if not possible.
Use `--with-systemdsystemunitdir=no` to disable this feature altogether.
--with-systemdshutdowndir=PATH
Where to install Linux systemd unit definitions for shutdown handling.
Useless and harmless on other OSes, including Linux distributions
without systemd, just adding a little noise to configure script output.
Use `--with-systemdshutdowndir` to detect the settings using pkg-config.
Use `--with-systemdshutdowndir=no` to disable this feature altogether.
--with-systemdtmpfilesdir=PATH
Where to install Linux systemd configuration for tmpfiles handling (the
automatically created locations for PID, state and similar run-time files).
Useless and harmless on other OSes, including Linux distributions
without systemd, just adding a little noise to configure script output.
Use `--with-systemdtmpfilesdir` to detect the settings using pkg-config.
Use `--with-systemdtmpfilesdir=no` to disable this feature altogether.
--with-augeas-lenses-dir=PATH
Where to install Augeas configuration-management lenses.
Only useful and valid if you use Augeas to parse and modify configuration
files. The default is to use `/usr/share/augeas/lenses`, if that directory
exists, and to not install it otherwise.
Directories used by NUT at run-time
@ -300,53 +523,87 @@ 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.
`/var/run`. Certain programs like `upsmon` will leave files here.
--with-altpidpath=PATH
Programs that normally don't have root powers, like the drivers and
upsd, write their pid files here. By default this is whatever the
statepath is, as those programs should be able to write there.
Programs that normally don't have `root` powers, like the drivers and
`upsd`, write their pid files here. By default this is whatever the
statepath (below) is, as those programs should be able to write there.
The `NUT_ALTPIDPATH` environment variable overrides this at run time.
--with-statepath=PATH
Change the default location of the state sockets created by the
drivers.
Change the default location of the state sockets created by the drivers
to interact with the data server `upsd`. Default is `/var/state/ups`.
The NUT_STATEPATH environment variable overrides this at run time.
Default is /var/state/ups.
The `NUT_STATEPATH` environment variable overrides this at run time.
Things the compiler might need to find
--------------------------------------
LibGD
~~~~~
--with-pkg-config
This option allows to provide a custom program name (in `PATH`) or a
complete pathname to `pkg-config` which describes `CFLAGS`, `LIBS` and
possibly other build-time options in `*.pc` files, to use third-party
libraries. On build systems which support multiple architectures you
may also want to set `PKG_CONFIG_PATH` to match your current build.
--with-gd-includes="-I/foo/bar"
If you installed gd in some place where your C preprocessor can't
find the header files, use this switch to add additional -I flags.
If you installed `libgd` in some place where your C preprocessor can't
find the header files, use this switch to add additional `-I` flags.
--with-gd-libs="-L/foo/bar -labcd -lxyz"
If your copy of gd isn't linking properly, use this to give the
proper -L and -l flags to make it work. See LIBS= in gd's Makefile.
If your copy of `libgd` isn't linking properly, use this to give the
proper `-L` and `-l` flags to make it work. See `LIBS=` in gd's `Makefile`.
NOTE: the --with-gd switches are not necessary if you have gd 2.0.8
or higher installed properly. The gdlib-config script will be
detected and used by default in that situation.
NOTE: the `--with-gd` switches are not necessary if you have gd 2.0.8
or higher installed properly. The `gdlib-config` script or pkg-config
manifest will be detected and used by default in that situation.
--with-gdlib-config
This option allows to provide a custom program name (in `PATH`) or
a complete pathname to `gdlib-config`. This may be needed on build
systems which support multiple architectures, or in cases where your
distribution names this program differently.
LibUSB
~~~~~~
--with-libusb-config
This option allows to provide a custom program name (in `PATH`) or
a complete pathname to `libusb-config` (usually delivered only for
libusb-0.1 version, but not for libusb-1.0). This may be needed on
build systems which support multiple architectures or provide several
versions of libusb, or in cases where your distribution names this
program differently.
Various
~~~~~~~
--with-ssl-includes, --with-usb-includes, --with-snmp-includes,
--with-neon-includes, --with-libltdl-includes,
--with-powerman-includes="-I/foo/bar"
If your system doesn't have pkg-config and support for any of the above
libraries isn't found (but you know it is installed), you must specify the
compiler flags that are needed.
libraries isn't found (but you know it is installed), you must specify
the compiler flags that are needed.
--with-ssl-libs, --with-usb-libs, --with-snmp-libs,
--with-neon-libs, --with-libltdl-libs
--with-powerman-libs="-L/foo/bar -labcd -lxyz"
If system doesn't have pkg-config or it fails to provides hints for some of the
settings that are needed to set it up properly and the build in defaults are
not right, you can specify the right variables here.
If system doesn't have pkg-config or it fails to provides hints for
some of the settings that are needed to set it up properly and the
build in defaults are not right, you can specify the correct values
for your system here.

View file

@ -74,7 +74,7 @@ When editing the genericups.h, the values have the following meanings:
Outgoing lines:
- line_norm = what to set to make the line "normal" - i.e. cable power
- line_norm = what to set to make the line "normal" -- i.e. cable power
- line_sd = what to set to make the UPS shut down the load
Incoming lines:
@ -83,6 +83,10 @@ Incoming lines:
- val_ol = value of that flag when the UPS is on battery
- line_bl = flag that appears for low battery / battery OK
- val_bl = value of that flag when the battery is low
- line_rb = flag that appears for battery health
- val_rb = value of that flag when the battery needs a replacement
- line_bypass = flag that appears for battery bypass / battery protection active
- val_bypass = value of that flag when the battery is bypassed / missing
This may seem a bit confusing to have two variables per value that
we want to read, but here's how it works. If you set line_ol to

220
docs/daisychain.txt Normal file
View file

@ -0,0 +1,220 @@
ifndef::external_title[]
[[daisychain]]
NUT daisychain support notes
============================
endif::external_title[]
NUT supports daisychained devices for any kind of device that proposes
it. This chapter introduces:
* for developers: how to implement such mechanism,
* for users: how to manage and use daisychained devices in NUT in general,
and how to take advantage of the provided features.
Introduction
------------
It's not unusual to see some daisy-chained PDUs or UPSs, connected together
in master-slave mode, to only consume 1 IP address for their communication
interface (generally, network card exposing SNMP data) and expose only one
point of communication to manage several devices, through the daisy-chain
master.
This breaks the historical consideration of NUT that one driver provides
data for one unique device. However, there is an actual need, and a smart
approach was considered to fulfill this, while not breaking the standard
scope (for base compatibility).
Implementation notes
--------------------
General specification
~~~~~~~~~~~~~~~~~~~~~
The daisychain support uses the device collection to extend the historical
NUT scope (1 driver -- 1 device), and provides data from the additional
devices accessible through a single management interface.
A new variable was introduced to provide the number of devices exposed: the
`device.count`, which:
* defaults to 1
* if higher than 1, enables daisychain support and access to data of each
individual device through `device.X.{...}`
To ensure backward compatibility in NUT, the data of the various devices
are exposed the following way:
* `device.0` is a special case, for the whole set of devices (the whole
daisychain). It is equivalent to `device` (without `.X` index) and root
collections. The idea is to be able to get visibility and control over the
whole daisychain from a single point.
* daisy-chained devices are available from `device.1` (master) to `device.N`
(slaves).
That way, client applications that are unaware of the daisychain support,
will only see the whole daisychain, as it would normally seem, and not
nothing at all.
Moreover, this solution is generic, and not specific to the ePDU use case
currently considered. It thus support both the current NUT scope, along with
other use cases (parallel / serial UPS setups), and potential evolution and
technology change (hybrid chain with UPS and PDU for example).
Devices status handling
^^^^^^^^^^^^^^^^^^^^^^^
To be clarified...
Devices alarms handling
^^^^^^^^^^^^^^^^^^^^^^^
Devices (master and slaves) alarms are published in `device.X.ups.alarm`,
which may evolve into `device.X.alarm`. If any of the devices has an alarm,
the main `ups.status` will publish an `ALARM` flag. This flag is be cleared
once all devices have no alarms anymore.
NOTE: ups.alarm behavior is not yet defined (all devices alarms vs. list of
device(s) that have alarms vs. nothing?)
Example
^^^^^^^
Here is an example excerpt of three PDUs, connected in daisychain mode, with
one master and two slaves:
device.count: 3
device.mfr: EATON
device.model: EATON daisychain PDU
device.1.mfr: EATON
device.1.model: EPDU MI 38U-A IN: L6-30P 24A 1P OUT: 36XC13:6XC19
device.2.mfr: EATON
device.2.model: EPDU MI 38U-A IN: L6-30P 24A 1P OUT: 36XC13:6XC19
device.3.mfr: EATON
device.3.model: EPDU MI 38U-A IN: L6-30P 24A 1P OUT: 36XC13:6XC19
...
device.3.ups.alarm: high current critical!
device.3.ups.status: ALARM
...
input.voltage: ??? (proposal: range or list or average?)
device.1.input.voltage: 237.75
device.2.input.voltage: 237.75
device.3.input.voltage: 237.75
...
outlet.1.status: ?? (proposal: "on, off, off)
device.1.outlet.1.status: on
device.2.outlet.1.status: off
device.3.outlet.1.status: off
...
ups.status: ALARM
Information for developers
~~~~~~~~~~~~~~~~~~~~~~~~~~
NOTE: these details are dedicated to the `snmp-ups` driver!
In order to enable daisychain support for a range of devices, developers
have to do two things:
* Add a `device.count` entry in a mapping file (see `*-mib.c`)
* Modify mapping entries to include a format string for the daisychain index
Optionally, if there is support for outlets and / or outlet-groups, there
is already a template formatting string. So you have to tag such templates
with multiple definitions, to point if the daisychain index is the first
or second formatting string.
Base support
^^^^^^^^^^^^
In order to enable daisychain support on a mapping structure, the following
steps have to be done:
* Add a "device.count" entry in the mapping file: snmp-ups will determine
if the daisychain support has to be enabled (if more than 1 device).
To achieve this, use one of the following type of declarations:
+
a) point at an OID which provides the number of devices:
{ "device.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.1.0", "1",
SU_FLAG_STATIC, NULL },
+
b) point at a template OID to guesstimate the number of devices, by walking
through this template, until it fails:
+
{ "device.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", "1",
SU_FLAG_STATIC, NULL, NULL },
* Modify all entries so that OIDs include the formatting string for the
daisychain index. For example, if you have the following entry:
+
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0", ... },
+
And if the last "0" of the the 4th field represents the index of the device
in the daisychain, then you would have to adapt it the following way:
+
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", ... },
Templates with multiple definitions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If there already exist templates in the mapping structure, such as for
single outlets and outlet-groups, you also need to specify the position
of the daisychain device index in the OID strings for all entries in the
mapping table, to indicate where the daisychain insertion point is exactly.
For example, using the following entry:
{ "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.0.%i",
NULL, SU_OUTLET, NULL, NULL },
You would have to translate it to:
{ "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL },
`SU_TYPE_DAISY_1` flag indicates that the daisychain index is the first
`%i` specifier in the OID template string. If it is the second one, use
`SU_TYPE_DAISY_2`.
Devices alarms handling
^^^^^^^^^^^^^^^^^^^^^^^
Two functions are available to handle alarms on daisychain devices in your
driver:
* `device_alarm_init()`: clear the current alarm buffer
* `device_alarm_commit(const int device_number)`: commit the current alarm
buffer to "device.<device_number>.ups.alarm", and increase the count of
alarms. If the current alarms buffer is empty, the count of alarm is
decreased, and the variable "device.<device_number>.ups.alarm" is removed
from publication. Once the alarm count reaches "0", the main (device.0)
ups.status will also remove the "ALARM" flag.
[NOTE]
======
When implementing a new driver, the following functions have to be
called:
* `alarm_init()` at the beginning of the main update loop, for the whole
daisychain. This will set the alarm count to "0", and reinitialize all
alarms,
* `device_alarm_init()` at the beginning of the per-device update loop.
This will only clear the alarms for the current device,
* `device_alarm_commit()` at the end of the per-device update loop.
This will flush the current alarms for the current device,
* also `device_alarm_init()` at the end of the per-device update loop.
This will clear the current alarms, and ensure that this buffer will not
be considered by other subsequent devices,
* `alarm_commit()` at the end of the main update loop, for the whole
daisychain. This will take care of publishing or not the "ALARM" flag
in the main ups.status (`device.0`, root collection).
======

View file

@ -39,7 +39,7 @@ The SERVER will connect to the socket of each DRIVER and will request a
dump at that time. It retains this data in local storage for later use.
It continues to listen on the socket for additional updates.
This protocol is documented in sock-protocol.txt.
This protocol is documented in link:sock-protocol.txt[].
From the server
~~~~~~~~~~~~~~~
@ -50,14 +50,14 @@ immediately. When a request for data arrives from a CLIENT, the SERVER
looks through the internal storage for that UPS and returns the
requested data if it is available.
The format for requests from the CLIENT is documented in protocol.txt.
The format for requests from the CLIENT is documented in link:protocol.txt[].
Instant commands
----------------
Instant commands is the term given to a set of actions that result in
"Instant commands" is the term given to a set of actions that result in
something happening to the UPS. Some of the common ones are
test.battery.start to initiate a battery test and test.panel.start to
`test.battery.start` to initiate a battery test and `test.panel.start` to
test the front panel of the UPS.
They are passed to the SERVER from a CLIENT using an authenticated
@ -69,9 +69,12 @@ information.
At this point, there is no confirmation to the SERVER of the command's
execution. This is (still) planned for a future release. This has been
delayed since returning a response involves some potentially interesting
timing issues. Remember that upsd services clients in a round-robin
timing issues. Remember that `upsd` services clients in a round-robin
fashion, so all queries must be lightweight and speedy.
NOTE: FIXME: Wasn't "TRACKING" mechanism for "INSTCMD/SET VAR" introduced
to address just this? See https://github.com/networkupstools/nut/pull/659
Setting variables
-----------------
@ -88,6 +91,9 @@ Like the instant commands, there is currently no acknowledgement of the
command's completion from the DRIVER. This, too, is planned for a future
release.
NOTE: FIXME: Wasn't "TRACKING" mechanism for "INSTCMD/SET VAR" introduced
to address just this? See https://github.com/networkupstools/nut/pull/659
Example data path
-----------------
@ -97,24 +103,24 @@ delivering the alpha message to the admin.
1. EQUIPMENT reports on battery by setting flag in status register
2. DRIVER notices this flag and stores it in the ups.status variable as
2. DRIVER notices this flag and stores it in the `ups.status` variable as
OB. This update gets pushed out to any listeners via the sockets.
3. SERVER upsd sees activity on the socket, reads it, parses it, and
3. SERVER `upsd` sees activity on the socket, reads it, parses it, and
commits the new data to its local version of the status variable.
4. CLIENT upsmon does a routine poll of SERVER for "ups.status" and
gets "OB".
4. CLIENT `upsmon` does a routine poll of SERVER for `ups.status` and
gets `OB`.
5. CLIENT upsmon then invokes its NOTIFYCMD which is upssched.
5. CLIENT `upsmon` then invokes its `NOTIFYCMD` which is `upssched`.
6. upssched starts up a daemon to handle a timer which will expire about
6. `upssched` starts up a daemon to handle a timer which will expire about
30 seconds into the future.
7. 30 seconds later, the timer expires since the UPS is still on battery,
and upssched calls the CMDSCRIPT upssched-cmd.
and so `upssched` calls the `CMDSCRIPT` which is `upssched-cmd`.
8. upssched-cmd parses the args and calls sendmail.
8. `upssched-cmd` parses the args and calls `sendmail`.
9. Avian carriers, smoke signals, SMTP, and some magic result in the
message getting from the pager company's gateway to a transmitter
@ -122,66 +128,66 @@ delivering the alpha message to the admin.
This scenario requires some configuration, obviously:
1. There's a UPS driver running.
1. There's an UPS driver running.
(Whatever applies for the hardware)
2. upsd has a valid UPS entry in ups.conf for this UPS.
2. `upsd` has a valid UPS entry in 'ups.conf' for this UPS.
[myups]
driver = nutupsdrv
port = /dev/ttySx
3. upsd has a valid user for upsmon in upsd.users.
3. `upsd` has a valid user for `upsmon` in 'upsd.users' file.
[monuser]
password = somepass
upsmon master
upsmon primary
4. upsmon is set to monitor this UPS in upsmon.conf.
4. `upsmon` is set to monitor this UPS with this user in 'upsmon.conf' file.
MONITOR myups@localhost 1 monuser somepass master
MONITOR myups@localhost 1 monuser somepass primary
5. upsmon is set to EXEC the NOTIFYCMD for the ONBATT condition in
upsmon.conf.
5. `upsmon` is set to `EXEC` the `NOTIFYCMD` for the `ONBATT` condition in
'upsmon.conf' file.
NOTIFYFLAG ONBATT EXEC
6. upsmon calls upssched as the NOTIFYCMD in upsmon.conf.
6. `upsmon` calls `upssched` as the `NOTIFYCMD` in 'upsmon.conf' file.
NOTIFYCMD /path/to/upssched
7. upssched has a 30 second timer for ONBATT in upssched.conf.
7. `upssched` has a 30 second timer for `ONBATT` in 'upssched.conf' file.
AT ONBATT * START-TIMER upsonbatt 30
8. upssched calls upssched-cmd as the CMDSCRIPT in upssched.conf.
8. `upssched` calls `upssched-cmd` as the `CMDSCRIPT` in 'upssched.conf'.
CMDSCRIPT /path/to/upssched-cmd
9. upssched-cmd knows what to do with "upsonbatt" as its first argument
(A quick case..esac construct, see the examples)
9. `upssched-cmd` knows what to do with `upsonbatt` keyword as its first
argument (a quick `case..esac` construct, see the examples)
History
-------
The oldest versions of this software (1998) had no separation between
the driver and the network server and only supported the latest APC
the driver and the network server, and only supported the latest APC
Smart-UPS hardware as a result. The network protocol used brittle
binary structs. This had numerous bad implications for compatibility
and portability.
After the driver and server were separated, data was shared through the
state file concept. Status was written into a static array (the "info
array") by drivers, and that array was stored on disk. upsd would
array") by drivers, and that array was stored on disk. The `upsd` would
periodically read that file into a local copy of that array.
Shared memory mode was added a bit later, and that removed some of the
lag from the status updates. Unfortunately, it didn't have any locking
originally, and the possibility for corruption due to races existed.
mmap() support was added at some point after that, and became the
default. The drivers and upsd would mmap() the file into memory and
`mmap()` support was added at some point after that, and became the
default. The drivers and `upsd` would `mmap()` the file into memory and
read or write from it. Locking was done using the state file as the
token, so contention problems were avoided. This method was relatively
quick, but it involved at least 3 copies of the data (driver, disk/mmap,
@ -194,12 +200,13 @@ connections and push updates asynchronously to any listeners. They also
recognize a few commands. Drivers also dampen updates, and only push
them out when something actually changes.
As a result, upsd no longer has to poll any files on the disk, and can
just select() all of its fds and wait for activity. When one of them is
active, it reads the fd and parses the results. Updates from the
hardware now get to upsd about as fast as they possibly can.
As a result, `upsd` no longer has to poll any files on the disk, and can
just `select()` all of its file descriptors (fds) and wait for activity.
When one of them is active, it reads the fd and parses the results.
Updates from the hardware now get to `upsd` about as fast as they possibly
can.
Drivers used to call setinfo() to change the local array, and then would
call writeinfo() to push the array onto the disk, or into the
Drivers used to call `setinfo()` to change the local array, and then would
call `writeinfo()` to push the array onto the disk, or into the
mmap/shared memory space. This introduced a lag since many drivers poll
quite a few variables during an update.

View file

@ -73,18 +73,19 @@ This mode allows to simulate any kind of devices, even non existing ones.
Using this method, you can either replay a real life sequence,
<<dev-recording,recorded from an actual device>>, or directly interact
through upsrw or by editing the device file, to modify the variables values.
through `upsrw` or by editing the device file, to modify the variables'
values.
Here is an example to setup a device simulation:
- install NUT as usual, if not already done
- get a simulation file (.dev) or sequence (.seq), or generate one using the
<<dev-recording,device recorder>>. Sample files are provided in the 'data'
directory of the NUT source. You can also download these from the development
repository, such as the
link:http://anonscm.debian.org/viewvc/nut/trunk/data/evolution500.seq?revision=2778&view=co[evolution500.seq].
- copy the simulation file to your sysconfig directory, like /etc/nut or
/etc/ups
- get a simulation file (`.dev`) or sequence (`.seq`), or generate one using
the <<dev-recording,device recorder>>. Sample files are provided in the
`data` directory of the NUT source. You can also download these from
the development repository, such as the
link:https://github.com/networkupstools/nut/raw/master/data/evolution500.seq[evolution500.seq].
- copy the simulation file to your sysconfig directory, like `/etc/nut`
or `/etc/ups`
- configure NUT for simulation (linkman:ups.conf[5]):
+
[dummy]
@ -92,7 +93,7 @@ link:http://anonscm.debian.org/viewvc/nut/trunk/data/evolution500.seq?revision=2
port = evolution500.dev
desc = "dummy-ups in dummy mode"
+
- now start NUT, at least dummy-ups and upsd:
- now start NUT, at least `dummy-ups` and `upsd`:
+
$ upsdrvctl start dummy
$ upsd
@ -102,13 +103,13 @@ link:http://anonscm.debian.org/viewvc/nut/trunk/data/evolution500.seq?revision=2
$ upsc dummy
...
+
- you can also use upsrw to modify the data:
- you can also use `upsrw` to modify the data in memory:
+
$ upsrw -s ups.status="OB LB" -u user -p password dummy
+
- or directly edit /etc/nut/evolution500.seq. In this case, modification will
only apply according to the TIMER events and the current position in the
sequence.
- or directly edit your copy of `/etc/nut/evolution500.seq`.
In this case, modification will only apply according to the `TIMER`
events and the current position in the sequence.
For more information, refer to linkman:dummy-ups[8] manual page.
@ -118,11 +119,11 @@ For more information, refer to linkman:dummy-ups[8] manual page.
Device recording
----------------
To complete dummy-ups, NUT provides a device recorder script called
'nut-recorder.sh' and located in the 'tools/' directory of the
To complete `dummy-ups`, NUT provides a device recorder script called
`nut-recorder.sh` and located in the 'tools/' directory of the
NUT source tree.
This script uses 'upsc' to record device information, and stores
This script uses `upsc` to record device information, and stores
these in a differential fashion every 5 seconds (by default).
Its usage is the following:
@ -134,8 +135,8 @@ For example, to record information from the device 'myups' every 10 seconds:
nut-recorder.sh myups@localhost myups.seq 10
During the recording, you will want to generate power events, such as power
failure and restoration. These will be tracked in the simulation files, and be
eventually be replayed by the <<dev-simu,dummy-ups>> driver.
failure and restoration. These will be tracked in the simulation files, and
be eventually be replayed by the <<dev-simu,dummy-ups>> driver.
NUT core development and maintenance
@ -159,8 +160,14 @@ Appendix A: NUT command and variable naming scheme
include::nut-names.txt[]
[[daisychain]]
Appendix B: NUT daisychain support notes
========================================
include::daisychain.txt[]
[[lib-info]]
Appendix B: NUT libraries complementary information
Appendix C: NUT libraries complementary information
===================================================
include::../lib/README[]

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more