Imported Upstream version 2.4.3

This commit is contained in:
arnaud.quette@free.fr 2010-03-26 00:20:59 +01:00
commit 26fb71b504
446 changed files with 148951 additions and 0 deletions

177
AUTHORS Normal file
View file

@ -0,0 +1,177 @@
# The NUT AUTHORS file. Don't be shy. If you have contributed to this
# project in some way, send me a patch to add yourself to this file.
#
# Everyone deserves credit, including those who haven't added any code.
# Ideas, clues, and helping out on the mailing lists all count too.
#
# This is a blatant ripoff of the fields found in the Linux kernel's CREDITS
# file. If we need more data, those fields can always be added later.
#
# N = name, E = email, W = web address, D = description, P = PGP info,
# S = snailmail address, etc.
#
# This file is supposed to be roughly alpha-sorted by the last name, but
# if you want to hide at the bottom, that's fine by me. Just clarify
# your preference when submitting changes to this file.
N: Stephen Brown
E: steve@datalimbo.net
W: http://www.datalimbo.net/
D: Hacked genericups to add TrippLite Lan2.x support (Internet Office 700)
N: Bill Carlson
E: wcarlson@wkks.org
W: http://wkks.org/
D: Fixed the GD/configure problem
N: Ben Collver
E: collver@softhome.net
W: http://superfluous.oddbox.org
D: Beginning support for HPUX 10.20 and Windows 2000
N: Luca Filipozzi
E: lfilipoz@debian.org
D: Original Debian maintainer for nut package. Minor patches to source.
N: Matthew Gabeler-Lee
E: msg2@po.cwru.edu
W: http://cheetah.cwru.edu
D: Added custom formatting to upslog
D: Helped get apcsmart working with old SmartUPS models
N: David Goncalves
E: david@lestat.st
W: http://www.lestat.st
D: Python client support (PyNUT module and NUT-Monitor application)
N: Bruno Hall
D: Contributed UPS compatibility information
N: Bo Kersey - VirCIO - Managed Server Solutions
E: bo@vircio.com
W: http://www.vircio.com/
D: Provided a Best Fortress for development of a Best driver (bestups)
N: Russell Kroll
E: rkroll@exploits.org
W: http://www.networkupstools.org/
D: Original NUT author and coordinator
P: 1024D/9DC0E77E 6A5C 7D2D 7945 C022 6104 D421 D61D C97F 9DC0 E77E
N: Rick Lyons
E: rick@powerup.com.au
D: Support for Liebert UPSes using MultiLink cable
N: Jeremy Maccelari
E: visualn@iafrica.com, jeremy@visuals.co.za
W: http://www.visuals.co.za
D: Support for Mustek UPSes
N: Philippe Marzouk
E: philm@users.sourceforge.net
D: Support for MGE Pulsar Ellipse UPSes ; co author of mge-shut
N: Theodor A. Milkov
E: zimage@delbg.com
W: http://www.delbg.com/~zimage/
D: Adding support for Repotec's RPT-800A, RPT-162A to genericups driver.
N: Mark Powell
E: medp@primagraphics.co.uk
D: Ported to SunOS4
N: Arnaud Quette
E: aquette.dev@gmail.com
E: arnaud.quette@mgeups.com
E: aquette@debian.org
W: http://arnaud.quette.free.fr/
D: Primary coordinator ; author of snmp-ups, mge-shut, usbhid-ups ;
D: co author of mge-utalk, hidups, SNMP UPS Agent ; contributor to blazer,
D: bestferrups, nut core, and many others ; coordination with MGE UPS
D: SYSTEMS, linux-usb developers (for hidups), Net SNMP and packagers
D: (Mandriva, Debian, SuSE, ...)...
P: 1024D/204DDF1B 1371 07DF 3CF3 9160 7905 144B DB64 14CA 204D DF1B
N: Lars Balker Rasmussen
E: lbr@mjolner.dk
D: Solaris and minor patches
N: Carlos Rodrigues
E: carlos.efr@mail.telepac.pt
W: http://students.fct.unl.pt/~cer09566/
D: author of the "megatec" driver
N: David Santinoli
E: david@santinoli.com
W: http://www.santinoli.com
D: Support for Online P-series in genericups driver
N: Jacob Schmier
E: j.schmier@live.com
D: support for Universal-Mount ON Series UPS family in oneac driver
N: Peter Selinger
E: selinger@users.sourceforge.net
W: http://www.mathstat.dal.ca/~selinger/
D: wrote belkinunv driver, contributions to usbhid-ups
P: 1024D/CA31696A 12A2 4B3C 3790 B688 E484 7A98 A68B CC37 CA31 696A
N: Kirill Smelkov
E: kirr@mns.spb.ru
D: Author of al175
N: John Stone
E: johns@megapixel.com
W: http://www.megapixel.com/
D: Support for Best MicroFerrups UPS
N: Technorama Ltd.
E: oss-list-ups@technorama.net
D: common driver core design, redundant code elimination, security fixes
D: other misc patches and improvements throughout
N: Jason Thomas
E: jason@topic.com.au
W: http://www.topic.com.au/
D: Hacked up the UPSonic Driver.
N: Simon Rozman
E: simon@rozman.net
W: http://simon.rozman.net/
D: Hacked powercom to add Socomec Sycon Egys 420 VA support
N: Len J White
E: lwhite@darkfires.net
N: Walt Holman
E: walt_h@lorettotel.net
D: Hacked up the cpsups driver for CyberPower text protocol UPSes
N: Fabio Di Niro
E: blaxwan@users.sourceforge.net
D: Author of metasys driver, support for Meta System UPS
N: Arjen de Korte
E: arjen@de-korte.org
D: Author of safenet driver
P: 1024R/AEF3BA11 664E 032C 9DB5 CB9B 7AFE 7EC1 EE88 BC57
N: Håvard Lygre
E: hklygre@online.no
D: First stab at upscode2 driver for NUT 1.4
N: Niels Baggesen
E: niels@baggesen.net
D: upgraded the upscode2 driver to NUT-2, and extended it heavily.
N: Niklas Edmundsson
E: nikke@acc.umu.se
D: 3-phase work, updates for upscode2
N: Olli Savia
E: ops@iki.fi
D: pwmib support for snmp-ups
N: Kjell Claesson
E: Kjell.claesson@epost.tidanet.se
D: Author of bcmxcp driver, 3-phase work.

12
COPYING Normal file
View file

@ -0,0 +1,12 @@
Most files are licensed under the GNU General Public License (GPL) version 2,
or (at your option) any later version. See "LICENSE-GPL2" in the root of this
distribution.
The files in the scripts/python/ directory are released under GNU General
Public License (GPL) version 3, or (at your option) any later version. See
"LICENSE.GPL3" in the root of this distribution.
The Perl client module (scripts/perl/Nut.pm) is released under the same
license as Perl itself. That is to say either GPL version 1 or (at your option)
any later version, or the "Artistic License".

1091
ChangeLog Normal file

File diff suppressed because it is too large Load diff

522
INSTALL Normal file
View file

@ -0,0 +1,522 @@
Network UPS Tools: INSTALL
These are the essential steps for compiling and installing this
software, including configuring safe shutdowns when the UPS battery
runs out of power.
There are many programs and other features in this package. You should
check out the README file and other accompanying documentation to see
how it all works.
The paths shown below are the default values you get by just calling
configure by itself. If you have used --prefix or similar, things will
be different. Also, if you didn't install this program from source
yourself, the paths will probably have a number of differences.
Note: by default, your system probably won't find the man pages, since
they install to /usr/local/ups/man. You can fix this by editing your
MANPATH, or just do this:
man -M /usr/local/ups/man <man page>
man -M /usr/local/ups/man upsd.conf
Also, if your favorite system offers up to date binary packages,
always prefer these over a source installation. Along with the known
advantages of such systems for installation, upgrade and removal, there
are many integration issues that have been addressed.
============================================================================
============================================================================
============================================================================
Prepare your system
===================
1. Create at least one user and a group for running this software. You
might call them "ups" and "nut". The exact names aren't important as
long as you are consistent.
The process for doing this varies from one system to the next, and
explaining how to add users is beyond the scope of this document.
For the purposes of this document, the user name and group name
will be "ups" and "nut" respectively.
Be sure the new user is a member of the new group! If you forget to
do this, you will have problems later on when you try to start upsd.
============================================================================
============================================================================
============================================================================
Build and install
=================
1. Configure the source tree for your system. Add the --with-user and
--with-group switch to set the user name and group that you created
above.
./configure --with-user=ups --with-group=nut
If you need any other switches for configure, add them here. For
example:
* to build and install USB drivers, add --with-usb (note that you
need to install libusb development package or files).
* to build and install SNMP drivers, add --with-snmp (note that
you need to install libsnmp development package or files).
* to build and install CGI scripts, add --with-cgi.
* to build and install NUT development files (needed to compile
WMNut and MGE PSP), add --with-lib.
* to build and install HAL support, add --with-hal.
See docs/configure.txt or "./configure --help" for the available
options.
If you alter paths with additional switches, be sure to use those
new paths while reading the rest of the steps.
*** Reference: docs/configure.txt
---------------------------------------------------------------------------
2. Build the programs.
make
This will build the NUT client and server programs and the
selected drivers. It will also build any other features that were
selected during configuration in step 1. above.
---------------------------------------------------------------------------
3. Gain privileges for installing software if necessary.
su
---------------------------------------------------------------------------
4. Install the files to a system level directory.
make install
This will install the compiled programs and man pages, as well as
some data files required by NUT. Any optional features selected
during configuration will also be installed.
This will also install sample versions of the NUT configuration
files. Sample files are installed with names like ups.conf.sample
so they will not overwrite any existing real config files you may
have created.
If you are packaging this software, then you will probably want to
use the DESTDIR variable to redirect the build into another place,
i.e.:
make DESTDIR=/tmp/package install
make DESTDIR=/tmp/package install-conf
---------------------------------------------------------------------------
5. Create the state path directory for the driver(s) and server to use
for storing UPS status data and other auxiliary files, and make it
owned by the user you created.
mkdir -p /var/state/ups
chmod 0770 /var/state/ups
chown root:nut /var/state/ups
---------------------------------------------------------------------------
6. Set ownership data and permissions on your serial or USB ports
that go to your UPS hardware. Be sure to limit access to just
the user you created earlier.
These examples assume the second serial port (ttyS1) on a typical
Slackware system. On FreeBSD, that would be cuaa1. Serial ports
vary greatly, so yours may be called something else.
chmod 0660 /dev/ttyS1
chown root:nut /dev/ttyS1
The setup for USB ports is slightly more complicated. Device files
for USB devices, such as /proc/bus/usb/002/001, are usually
created "on the fly" when a device is plugged in, and disappear
when the device is disconnected. Moreover, the names of these
device files can change randomly. To set up the correct
permissions for the USB device, you may need to set up (operating
system dependent) hotplugging scripts. Sample scripts and
information are provided in the scripts/hotplug and
scripts/udev directories. For most users, the hotplugging scripts
will be installed automatically by "make install".
(If you want to try if a driver works without setting up
hotplugging, you can add the "-u root" option to upsd, upsmon, and
drivers; this should allow you to follow the below
instructions. However, don't forget to set up the correct
permissions later!).
NOTE: if you are using something like devfs or udev, make sure
these permissions stay set across a reboot. If they revert to the
old values, your drivers may fail to start.
---------------------------------------------------------------------------
7. Create one section per UPS in /usr/local/ups/etc/ups.conf
To find out which driver to use, check the "HARDWARE SUPPORT TABLE"
in the README file, or data/driver.list.
Once you have picked a driver, create a section for your UPS in
ups.conf. You must supply values 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.
A typical UPS without any extra settings looks like this:
[myupsname]
driver = mydriver
port = /dev/ttyS1
desc = "Workstation"
NOTE: usbhid-ups is a special case and ignores the "port" value.
You must still set this value, but it does not matter what you set
it to; you can set "port" to "auto" if you like. If you only own
one local UBS UPS, the driver will find it automatically. If you
own more than one UBS UPS, refer to the usbhid-ups(8) man page for
more information.
*** References: man pages: ups.conf(5), nutupsdrv(8), plus
whatever driver(s) you intend to use.
---------------------------------------------------------------------------
8. Start the driver(s) for your hardware.
/usr/local/ups/bin/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 belkin driver looks like this:
# /usr/local/ups/bin/upsdrvctl start
Network UPS Tools - UPS driver controller 1.5.12
Network UPS Tools - Belkin Smart protocol driver 0.21 (1.5.12)
Detected F6C525-SER on /dev/cuaa0
#
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.
Be sure to check the driver's man page to see if it needs any extra
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
permissions and mode on that directory (step 5).
After making changes, try step 6 again.
*** References: man pages: nutupsdrv(8), upsdrvctl(8)
---------------------------------------------------------------------------
9. 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
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.
LISTEN 127.0.0.1 3493
LISTEN ::1 3493
Note: if you run a firewall of some sort, you may have to add rules
to allow these incoming connections.
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.
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
group you created, then make it readable by the group.
chown root:nut upsd.conf upsd.users
chmod 0640 upsd.conf upsd.users
*** References: man pages: upsd.conf(5), upsd.users(5), upsd(8)
---------------------------------------------------------------------------
10. Start the network server.
/usr/local/ups/sbin/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
Network UPS Tools upsd 1.5.12
Connected to UPS [belkin]: belkin-cuaa0
Synchronizing...done
#
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
have a driver that isn't working properly. You must fix this before
going on to the next step.
*** Reference: man page: upsd(8)
---------------------------------------------------------------------------
11. Make sure that the UPS is providing good status data.
/usr/local/ups/bin/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
probably misconfigured in step 7. If you reconfigure the driver,
use 'upsdrvctl stop' to stop it, then start it again in step 8.
*** Reference: man page: upsc(8)
---------------------------------------------------------------------------
12. Look at all of the status data which is being monitored.
/usr/local/ups/bin/upsc myupsname@localhost
What happens now depends on the kind of UPS and driver you have.
In the list, you should see ups.status with the same value you got
above. A sample run on a MGE UPS SYSTEMS Ellipse ASR 600 looks
like this:
battery.charge: 82
battery.charge.low: 30
battery.runtime: 1563
driver.name: usbhid-ups
driver.parameter.port: auto
driver.version: 2.0.3
driver.version.data: MGE HID 0.8
driver.version.internal: 0.28
input.transfer.high: 264.0
input.transfer.low: 184.0
outlet.desc: Main Outlet
outlet.id: 1
outlet.switchable: 0
outlet.1.desc: PowerShare Outlet 1
outlet.1.id: 2
outlet.1.switch: 0
outlet.1.switchable: 0
output.voltage: 230.0
ups.delay.shutdown: -1
ups.delay.start: -10
ups.load: 0
ups.mfr: MGE UPS SYSTEMS
ups.model: Ellipse 600
ups.power.nominal: 600
ups.serial: AP8F15005
ups.status: OB DISCHRG
*** Reference: man page: upsc(8)
---------------------------------------------------------------------------
13. Edit your startup scripts.
Make sure upsdrvctl and upsd are run every time your system starts.
============================================================================
============================================================================
============================================================================
Configuring shutdowns for low battery events
--------------------------------------------
The whole point of UPS software is to bring down the OS cleanly when you
run out of battery power. Everything else is just eye candy. To make
sure your system shuts down properly, you will need to perform some
additional configuration and run upsmon. Here are the basics:
---------------------------------------------------------------------------
1. 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":
[monuser]
password = mypass
upsmon master # or upsmon slave
*** References: man pages: upsd(8), upsd.users(5)
---------------------------------------------------------------------------
2. Reload upsd. Depending on your configuration, you may be able to
do this without stopping upsd:
/usr/local/ups/sbin/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
Later: if you want to make reloading work, see the entry in the FAQ
about starting upsd as a different user.
---------------------------------------------------------------------------
3. 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
during a power failure when low battery is reached.
We will test for the presence of this file in a later step.
POWERDOWNFLAG /etc/killpower
*** References: man pages: upsmon(8), upsmon.conf(5)
---------------------------------------------------------------------------
4. Secure 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.
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.
---------------------------------------------------------------------------
5. Create a MONITOR directive for upsmon
Edit upsmon.conf and create a MONITOR line with the UPS definition
(<upsname>@<hostname>), username and password from step 2, and
the master or slave setting.
If it's the master (i.e., it's connected to this UPS directly):
MONITOR myupsname@mybox 1 monuser mypass master
If it's just monitoring this UPS over the network, and some other
system is the master:
MONITOR myupsname@mybox 1 monuser mypass slave
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. See big-servers.txt and data-room.txt.
*** References: man pages: upsmon(8), upsmon.conf(5)
---------------------------------------------------------------------------
6. 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:
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.
---------------------------------------------------------------------------
7. Start upsmon.
/usr/local/ups/sbin/upsmon
If it complains about something, then check your configuration.
---------------------------------------------------------------------------
8. 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
logged into UPS [myupsname]
Any errors seen here are probably due to an error in the config
files of either upsmon or upsd. You should fix them before
continuing.
---------------------------------------------------------------------------
9. Edit your startup scripts: add 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.
---------------------------------------------------------------------------
10. Edit your shutdown scripts: 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 upsmon.conf), using this as an example:
if (test -f /etc/killpower)
then
echo "Killing the power, bye!"
/usr/local/ups/bin/upsdrvctl shutdown
sleep 120
# uh oh... the UPS power-off failed
# you probably want to reboot here so you don't get stuck!
# *** see the section on power races in shutdown.txt! ***
fi
Be careful: that upsdrvctl command will probably power off your
machine. Don't use it unless your system is ready to be halted by
force. If you run RAID, be sure the arrays are ready to lose power.
Your kernel's power-off routines may not execute.
Make sure that the filesystem(s) holding your UPS drivers and
configuration details are still mounted when that part of the script
is run. You need upsdrvctl, ups.conf, and any drivers for the
hardware on your system.
---------------------------------------------------------------------------
More information can be found in the README file, the shutdown.txt document,
the upsmon(8) man page and the upsmon.conf(5) man page.

66
MAINTAINERS Normal file
View file

@ -0,0 +1,66 @@
In the tradition of stealing ideas for top-level files from the Linux
kernel tree, here is the NUT MAINTAINERS file. This file is intended to
help patch contributors route their changes to the right people.
Note: just because something isn't listed in here doesn't mean it's not
being maintained. It just means that the maintainer hasn't sent me a
patch to update this file yet.
Note 2: there are always other people who work on a project beyond those
who are listed here. Omission from this list should not be taken as a
slight. Those who are listed below are merely volunteering to be the
"lightning rods" for patches to certain parts of the tree.
Fields
======
P: Person
M: Mail patches to this address
W: Web address
S: Status:
Supported = someone is paid to do this
Maintained = someone keeps it running
(add others as necessary)
In the case of drivers, "maintained" should only be used if you have
access to the hardware in question for testing.
Drivers
=======
P: Russell Kroll
M: rkroll@exploits.org
S: Maintained: apcsmart, belkin, bestups, cyberpower, dummycons,
fentonups, driver core (main.c), upsdrvctl
P: Arnaud Quette
M: aquette.dev@gmail.com
M: arnaud.quette@mgeups.com
S: Maintained or Supported: dummy-ups, usbhid-ups, mge-shut, newmge-shut
mge-utalk, snmp-ups, HAL support
P: Arjen de Korte
M: arjen@de-korte.org
S: Maintained: safenet, genericups, powerpanel, netxml-ups, usbhid-ups
P: Fabio Di Niro
M: blaxwan@users.sourceforge.net
S: Maintained: metasys
Packaging
=========
P: Nigel Metheringham
M: Nigel.Metheringham@dev.InTechnology.co.uk
S: Maintained: nut.spec.in (for Red Hat RPM builds)
P: Arnaud Quette
M: aquette@debian.org
S: Maintained: Official Debian packages
Everything else
===============
No other categories have been created yet.

87
Makefile.am Normal file
View file

@ -0,0 +1,87 @@
# top-level Makefile for NUT
# include directory for aclocal
ACLOCAL_AMFLAGS = -I m4
# subdirectories to build and distribute. The order matters, as
# several subdirectories depend on stuff in "common" being built first
SUBDIRS = include common clients conf data docs drivers lib man \
tools scripts server
EXTRA_DIST = 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.
DISTCHECK_FLAGS = --with-all --with-ssl --with-ipv6
DISTCHECK_LIGHT_FLAGS = --with-all=auto --with-ssl=auto --with-ipv6=auto
DISTCHECK_CONFIGURE_FLAGS = ${DISTCHECK_FLAGS} \
--with-hotplug-dir='$${prefix}/etc/hotplug' \
--with-udev-dir='$${prefix}/etc/udev'
distcheck-light:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_FLAGS)" distcheck
# workaround the dist generated files that are also part of the distribution
distcleancheck_listfiles = \
find . -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
# ----------------------------------------------------------------------
# targets from old build system (pre-automake).
# supported for a period of time for backward "compatibility".
WARN="----------------------------------------------------------------------"
build:
@echo $(WARN)
@echo "Warning: 'make build' is deprecated. Use 'make all' instead."
@echo $(WARN)
$(MAKE) $(AM_MAKEFLAGS) all
install-bin:
@echo $(WARN)
@echo "Warning: 'make install-bin' is deprecated."
@echo "Use 'make install-exec' instead for a similar effect."
@echo $(WARN)
cd common; $(MAKE) $(AM_MAKEFLAGS) install
cd drivers; $(MAKE) $(AM_MAKEFLAGS) install
cd server; $(MAKE) $(AM_MAKEFLAGS) install
cd clients; $(MAKE) $(AM_MAKEFLAGS) install
install-man: install-data-recursive
@echo $(WARN)
@echo "Warning: 'make install-man' is deprecated."
@echo "Use 'cd man; make install' instead."
@echo $(WARN)
cd man; $(MAKE) $(AM_MAKEFLAGS) install
install-conf:
@echo $(WARN)
@echo "Warning: 'make install-conf' is deprecated."
@echo "Use 'cd conf; make install' instead."
@echo $(WARN)
cd conf; $(MAKE) $(AM_MAKEFLAGS) install
# The target install-data already has a standardized meaning under automake
install-dirs:
@echo $(WARN)
@echo "Warning: 'make install-dirs' is deprecated."
@echo "Use 'make installdirs' instead."
@echo $(WARN)
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."
@echo "Use './configure --with-cgi' instead."
install-lib:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-lib' instead."
usb build-usb install-usb:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-usb' instead."
snmp build-snmp install-snmp install-snmp-mgr install-snmp-man:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-snmp' instead."
setver:
@echo "Error: 'make setver' no longer exists."
@echo "Edit configure.in to set version number."

839
Makefile.in Normal file
View file

@ -0,0 +1,839 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# top-level Makefile for NUT
VPATH = @srcdir@
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 = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \
ChangeLog INSTALL NEWS compile config.guess config.sub depcomp \
install-sh ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
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 =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
install-html-recursive install-info-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
distdir dist dist-all distcheck
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d "$(distdir)" \
|| { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr "$(distdir)"; }; }
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
# include directory for aclocal
ACLOCAL_AMFLAGS = -I m4
# subdirectories to build and distribute. The order matters, as
# several subdirectories depend on stuff in "common" being built first
SUBDIRS = include common clients conf data docs drivers lib man \
tools scripts server
EXTRA_DIST = 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.
DISTCHECK_FLAGS = --with-all --with-ssl --with-ipv6
DISTCHECK_LIGHT_FLAGS = --with-all=auto --with-ssl=auto --with-ipv6=auto
DISTCHECK_CONFIGURE_FLAGS = ${DISTCHECK_FLAGS} \
--with-hotplug-dir='$${prefix}/etc/hotplug' \
--with-udev-dir='$${prefix}/etc/udev'
# workaround the dist generated files that are also part of the distribution
distcleancheck_listfiles = \
find . -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
# ----------------------------------------------------------------------
# targets from old build system (pre-automake).
# supported for a period of time for backward "compatibility".
WARN = "----------------------------------------------------------------------"
all: all-recursive
.SUFFIXES:
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
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);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@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
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -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
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-lzma: distdir
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
$(am__remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(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 --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@$(am__cd) '$(distuninstallcheck_dir)' \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-libtool \
distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
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
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am am--refresh check check-am clean clean-generic \
clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
dist-gzip dist-lzma 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-recursive uninstall uninstall-am
distcheck-light:
$(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_FLAGS)" distcheck
build:
@echo $(WARN)
@echo "Warning: 'make build' is deprecated. Use 'make all' instead."
@echo $(WARN)
$(MAKE) $(AM_MAKEFLAGS) all
install-bin:
@echo $(WARN)
@echo "Warning: 'make install-bin' is deprecated."
@echo "Use 'make install-exec' instead for a similar effect."
@echo $(WARN)
cd common; $(MAKE) $(AM_MAKEFLAGS) install
cd drivers; $(MAKE) $(AM_MAKEFLAGS) install
cd server; $(MAKE) $(AM_MAKEFLAGS) install
cd clients; $(MAKE) $(AM_MAKEFLAGS) install
install-man: install-data-recursive
@echo $(WARN)
@echo "Warning: 'make install-man' is deprecated."
@echo "Use 'cd man; make install' instead."
@echo $(WARN)
cd man; $(MAKE) $(AM_MAKEFLAGS) install
install-conf:
@echo $(WARN)
@echo "Warning: 'make install-conf' is deprecated."
@echo "Use 'cd conf; make install' instead."
@echo $(WARN)
cd conf; $(MAKE) $(AM_MAKEFLAGS) install
# The target install-data already has a standardized meaning under automake
install-dirs:
@echo $(WARN)
@echo "Warning: 'make install-dirs' is deprecated."
@echo "Use 'make installdirs' instead."
@echo $(WARN)
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."
@echo "Use './configure --with-cgi' instead."
install-lib:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-lib' instead."
usb build-usb install-usb:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-usb' instead."
snmp build-snmp install-snmp install-snmp-mgr install-snmp-man:
@echo "Error: 'make $@' no longer exists."
@echo "Use './configure --with-snmp' instead."
setver:
@echo "Error: 'make setver' no longer exists."
@echo "Edit configure.in to set version number."
# 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:

979
NEWS Normal file
View file

@ -0,0 +1,979 @@
If you're upgrading from an earlier version, see the UPGRADING file.
For a complete list of changes, please refer to the ChangeLog file.
---------------------------------------------------------------------------
Release notes for NUT 2.4.3 - what's new since 2.4.2:
- this is a bugfix release that only solves the regression on IPv6 activation.
---------------------------------------------------------------------------
Release notes for NUT 2.4.2 - what's new since 2.4.1:
- the general USB support has been vastly improved, including many bug
fixes, better OS support, new features and devices.
- NUT now talks to Solar Controller Devices with the new ivtscd driver.
- the snmp-ups driver supports more PDU, with a smaller disk footprint.
- apcsmart supports more older SmartUPS and Matrix units.
- the bestfortress driver is resurrected.
- the virtual driver has been renamed to 'clone'.
- the netxml-ups driver has received some care.
- various debugging and development improvements have been done, around
driver output; dummy-ups with more interaction and scripting and the
device-recorder.sh script.
- the build system has received many bugfixes and improvements.
- the UPower (previously known as DeviceKit-power) rules file is now
generated by NUT.
- support for new devices: Apollo 1000A and 1000F; various Baytech RPC; old
Best Power Fortress; Cyber Power Systems PR3000E, CP 1500C and OR2200LCDRM2U;
all the new Dell UPS range (serial, USB and network); Eaton E Series NV and
DX UPS, and Powerware 9130; older HP T500 and T750, newer T750 INTL (USB) and
R1500 G2 (serial); Inform Informer Compact 1000VA; many serial and USB
devices from Ippon, like Back Comfo Pro, Smart Power Pro and Smart Winner;
IVT SCD series; Liebert GXT2-3000RT230 and PowerSure PSA; Mustek PowerMust
424 / 636 / 848 USB; all new PowerCOM USB devices with HID PDC interface;
Tripp-Lite INTERNETOFFICE700, SMART700USB and ECO550UPS; UPSonic DS-800
(USB).
---------------------------------------------------------------------------
Release notes for NUT 2.4.1 - what's new since 2.4.0:
- the microdowell driver has appeared to support various MicroDowell Enterprise
units (see the "new devices" list below).
- support for new devices: MicroDowell Enterprise B8, B10, N8, N11, N15, N20,
N22, N30, N40, N50, N60 and HiBox ST.
- NUT-Monitor now better handles the ups.status field, and has switched to
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
further configure call.
---------------------------------------------------------------------------
Release notes for NUT 2.4.0 - what's new since 2.2.2:
- preliminary support for Power Distribution Units (PDUs): NUT now support
PDUs, either natively (ie using NUT snmp-ups driver), or through a binding to
the Powerman daemon. The list of supported PDUs is already quite long,
including: Eaton ePDUs (Managed and Monitored), some Aphel models, some
Raritan PDUs, and the whole list of Powerman supported devices:
http://powerman.sourceforge.net/supported.html
- support for new devices: the various PDUs cited above, Chloride Desk Power
650, Cyber Power Systems Value 400E/600E/800E (USB models), Delta GES602N,
Digitus DN-170020, the whole Eaton ranges (mostly composed of MGE Office
Protection Systems and Powerware units) including BladeUPS, Forza Power
Technologies SL-1001, HP PowerTrust 2997A, HP R/T 2200 G2, Infosec XP 1000
and XP 500, Ippon Back Power Pro (serial and USB), Kebo 1200D/D Series,
Liebert PowerSure Personal XT, MGE Office Protection Systems Protection
Station, Neus 400va and 600va, Phasak 400VA and 600VA, Plexus 500VA, Powercom
Black Knight PRO / King PRO and Imperial, PowerKinetics BlackOut Buster,
Sweex 1000 USB, UNITEK Alpha 500, WinPower CPM-800.
- NUT now embeds Python client support through the PyNUTClient module and the
NUT-Monitor application. Both are from David Goncalves, and are still
available from http://www.lestat.st.
For more information, refer to scripts/python/README.
- the dummy-ups driver now support a "repeater" mode. This allows it to act as
a NUT client, and to forward data. This can be useful for supervision and
load sharing purposes.
- tcp-wrappers support has been added to the upsd server, to grant users access
by source IP for commands that require to be logged into the server. This
replaces the previous internal implementation (ACL in upsd.conf).
- the nut.conf file has been introduced to standardize startup configuration
across the various systems.
- 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
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
files,
- the upsdrv_info_t structure to track more driver information, and remove
the need for the upsdrv_banner() function
- common USB code refactoring, as it is done for the serial functions.
- tons of bugfixes, cleanup and improvements to make NUT stronger than ever!
---------------------------------------------------------------------------
Release notes for NUT 2.2.2 - what's new since 2.2.1:
- support for new devices: APC BACK-UPS XS LCD, Atlantis Land,
Mustek Powermust Office 650, Oneac XAU models, Powerware PW5115 and
PW9120 (USB), Nitram Elite 2005
- Integrated Power Management (NUT HAL integration) has reached a
major milestone: it is now the most advanced UPS integration into
Power Management layer known in existing OSs. It has received many
corrections and improvements, and allows to PowerOff the UPS at the
end of a power cycle (which is the most important feature, not
supported on other systems).
The various files are now installed into the correct location.
- the usbhid-ups driver has received attention. Most notably, the
shutdown handling has been reworked, and support for MGE UPS SYSTEMS
3 phases units has been added.
- snmp-ups now supports MGE* Environment Sensor (ref 66 846).
The ambient.temperature reporting has also been fixed for units
other than APC.
- the netxml-ups driver has appeared to support MGE* network HTTP/XML
cards.
- NUT now distributes by default the shared version of libupsclient
(version 1.0.0), and use this for the provided clients (upsmon, upsc,
upsrw, upscmd). This is part of an effort to reduce NUT's footprint,
both on disk and in memory.
- powerpanel has reach a new step toward the replacement of nitram and
cpsups drivers. The final step is scheduled for NUT 2.4.
- many changes, cleanup and fixes to the NUT core and various drivers.
---------------------------------------------------------------------------
Release notes for NUT 2.2.1 - what's new since 2.2.0:
- support for new devices: all MGE Office Protection Systems units,
Advice TopGuard 2000, Belkin F6H375-USB, Dynamix UPS1700D, Effekta RM2000MH,
Jageson Technology Jasuny USPS, Powercom SMK-1500A and SXL-1500A,
PowerWalker Line-Interactive VI 400/800 and 600, Powerware 9110,
UNITEK Alpha 2600, UPSonic CXR1000, some vintage serial APC UPSs.
- the usbhid-ups driver has been improved, and fixed in many areas, through
a backport of the development (trunk) version.
- the udev rules, for Linux hotplug support of the USB UPSs, has been
updated to support kernel newer than 2.6.22.
- the megatec and megatec_usb drivers have also been backported from the
development (trunk) version.
- the client development files have also received some care:
the upsclient pkg-config file has been fixed, and the upsclient.h
file allows older NUT clients to continue using the UPSCONN structure.
---------------------------------------------------------------------------
Release notes for NUT 2.2.0 - what's new since 2.0.5:
- The new build infrastructure, using automake, is now used.
This has major impact on the compilation and installation procedures,
and thus on the NUT packaging.
For more information, refer to UPGRADING and packaging/debian/ for
an example of migration.
- NUT now provides support for FreeDesktop Hardware Abstraction Layer
(HAL) which brings full Plug And Play experience to USB UPS owners.
For more information, refer to docs/nut-hal.txt.
- support for new devices: Ablerex 625L, ActivePower 400VA, 2000VA;
Belkin Home Office F6H350-SER, F6H500-SER, F6H650-SER; Belkin Office
Series F6C550-AVR; Belkin Universal UPS F6C100-UNV (USB), F6C1100-UNV
(USB), F6C1200-UNV (USB), F6H350deUNV (serial), F6H350ukUNV (serial),
F6H650ukUNV (serial); Compaq R3000h; Cyber Power Systems PR2200;
Dynex DX-800U; Geek Squad GS1285U; Krauler UP-M500VA; Mecer ME-2000;
MGE UPS SYSTEMS Ellipse MAX; Online Zinto D; PowerTech SMK-800; SVEN
Power Pro+ series, Power Smart RM 2000; Tripp-Lite SmartOnline
SU1500RTXL2ua, smart2200RMXL2U.
- added IPv6 support,
- the newmge-shut driver has appeared. This one uses the same HID core
as usbhid-ups, but communicate over a serial link. It will eventually
replace the current mge-shut driver.
- client commands (upsc, upsrw and upscmd): hostname is now optional,
and defaults to "localhost"
- many drivers have been improved and have received bug fixes:
powerpanel, megatec, megatec_usb, safenet, tripplite_usb, gamatronic,
- the hotplug and udev scripts, in charge of setting the right
permissions on the USB devices, are now installed automatically
when appropriate.
- more generally, the NUT core and documentation, including the manpages,
have been improved and updated.
---------------------------------------------------------------------------
Release notes for NUT 2.0.5 - what's new since 2.0.4:
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
for new models.
- support for new devices: APC Smart-UPS with 6TI firmware; Belkin
Small Enterprise F6C1500-TW-RK; Compaq R3000 XR, R5500 XR; Cyber
Power 550SL, 725SL, 685AVR, 800AVR, 1200AVR, AE550; Eltek; Inform
GUARD; Microsol Rhino; Opti-UPS PowerES 420E; PowerMan RealSmart,
BackPro; Powerware PW9315 3-phase; SOLA 305; Tripp-Lite
SMART550USB, SMART2200RMXL2U, OMNI1000LCD, OMNI900LCD, OMNI650LCD,
1500 LCD, AVR550U; Viewsonic PowerES 420E.
- bcmxcp: added 3-phase support
- megatec: better hardware support, more instant commands
- mge-hid: support more instant commands
- newhidups: fixed APC and Tripp Lite bugs, various memory bugs,
improved report buffering, improved Solaris support, added
'-x explore' option for easy diagnosis of new devices
- solis: shutdown programming, support new cables, Solaris support
- tripplite_usb: updated SMARTPRO support, fixed OL/OB reporting,
better error handling, some memory bugs
- new dummy-ups driver simulator
- added HTML interface for access to CGI scripts
---------------------------------------------------------------------------
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
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
through the NTP - Network Time Protocol.
[Arjen de Korte]
- The mge-shut driver now better detects the Low Battery status, support
new models and fixes some wrong status and data. It also fixes some
issue where the UPS wasn't restarting (refer to mge-shut manpage).
[Arnaud Quette]
- The genericups custom configuration through ups.conf is working again
[Arjen de Korte]
- The genericups driver type 22 also support CyberPower 725SL
(and maybe others SL models)
[David Kaufman]
- The new megatec driver, which will replace a bunch of drivers by nut 2.2
(refer to docs/megatec.txt and UPGRADING) has been backported from the
trunk (Development tree). The powermust driver has also received some
attention.
[Carlos Rodrigues]
- The new rhino driver was added to support Microsol Rhino UPS hardware
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]
- Several fixes and improvements have been made to upsrw, upsset,
cpsups, tripplite_usb and the FAQ.
[Arjen de Korte and Charles Lepple]
---------------------------------------------------------------------------
Release notes for NUT 2.0.3 - what's new since 2.0.2:
- The recent and major newhidups changes have been backported from the
Development tree. It now:
- supports models from MGE UPS SYSTEMS, APC and Belkin. Mustek and Unitek
units are also recognized for development purpose,
- handles better device reopening, after a disconnection,
- handles multiple devices, with several parameters to find the right UPS.
[Peter Selinger, Charles Lepple and Arnaud Quette]
- The bcmxcp_usb driver has been added to support Powerware USB units.
[Wolfgang Ocker and Kjell Claesson]
- The tripplite_usb driver has been added to support Tripp Lite USB units.
[Charles Lepple]
- The sec driver is back as gamatronic
[Gamatronic, Nadav Moskovitch]
- The genericups driver has received official care from Gamatronic
to add support for the Gamatronic UPS with alarm interface.
[Gamatronic, Nadav Moskovitch]
- The powermust driver now supports Soyntec Sekury C 500 and C 800 units.
[Hanno Borns]
- The mge-shut driver has received a bit of attention too, and enhance
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
failure to poweroff the UPS if /var is already unmounted.
[Gaspar Bakos]
- The belkinunv driver now supports Belkin F6C1100-UNV
[Dave Breiland]
- The isbmex driver has been upgraded to version 0.05, which fixes
various errors in formulas, add shutdown capability and revert
back baudrate to B9600 (instead of B2400), as it broke the
communication
[Ricardo Martinezgarza]
- The support of Sysgration UPGUARDS Pro650 in fentonups has
been fixed
[Simon J. Rowe]
- The packaging files for Red Hat have received various fixes
[Thomas Jarosch]
- The solis driver has been fixed to avoid a naming colision and
compile on Solaris
[Paweł Kierdelewicz]
- The snmp-ups driver has corrected the problem when exposing
certain time data.
---------------------------------------------------------------------------
Release notes for NUT 2.0.2 - what's new since 2.0.1:
- the newhidups USB driver has been improved a lot and is no more
experimental. It also now has a basic APC support, which will
soon replace the legacy hidups driver.
- The mge-utalk driver has improved its support for old units.
- The mge-shut driver has been improved for restart/shutdown
sequences which was previously blocking the serial port.
- The general MGE support has been added Pulsar EXtreme C / EX RT,
Comet EX RT, Pulsar SV, Pulsar PSX, Ellipse Office and NOVA AVR USB.
- The genericups driver now supports Generic RUPS 2000, AEC MiniGuard
UPS 700 (using Megatec M2501 cable), and Powerware 3110.
[Nick Barnes, Paul Andreassen]
- The powermust driver now supports SquareOne Power QP1000, Mustek
PowerMust 1400VA Plus and 2000VA USB.
[Carlos Rodrigues]
- The fentonups driver has been enhanced and now supports Sysgration
UPGUARDS Pro650.
[Michel Bouissou, Simon J. Rowe]
- The cpsups driver now supports MicroDowell B.Box BP 500/750/1000/1500.
[Armin Diehl]
- The snmp-ups driver now supports Socomec SNMP devices (Netvision MIB),
and Powerware ConnectUPS SNMP cards.
[Thanos Chatziathanassiou, Olli Salvia]
- The bcmxcp driver is back with support for Powerware UPSs.
[Tore Øpetveit, Kjell Claesson]
- The cyberpower driver now supports CyberPower 1000AVR.
[Dave Huang]
- The new solis driver supports Microsol units: Solis 1.0, 1.5,
2.0 and 3.0.
[Silvino B. Magalhaes]
- The apcsmart driver has fixed APC600 support.
- The etapro driver fixes brokeness due to ser_get_line use
[Marek Michalkiewicz]
- The new upscode2 driver supports Fiskars, Compaq and Powerware
devices.
[Niels Baggesen, Havard Lygre]
- The tripplite driver has fixed a battery charge bug
[Cedric Tefft]
---------------------------------------------------------------------------
Release notes for NUT 2.0.1 - what's new since 2.0.0:
- The bestuferrups driver has been forked into the new bestfcom driver
which has better handling of the inverter status alarm messages and
more.
[Kent Hill]
- Mustek UPS support returns with two drivers which have overlapping
coverage: mustek and powermust.
[powermust: Carlos Rodrigues, mustek: Martin Hajduch]
- Additional CyberPower Systems hardware is supported with the new
cpsups driver. Three recognized models are the CPS1500AVR,
CPS1100VA, and OP500TE.
[Walt Holman, Brad Sawatzky]
- The genericups driver can now generate staleness warnings in
specific cases where the UPS provides a way to test for its
presence. See the "CON" setting in ups.conf for more details.
[stan / saticed.me.uk]
- Documentation for monitoring a Back-UPS RS 500 on a system without
USB ports has been added to the cables directory.
[Martin Edlman]
- The everups driver now supports types 73-76 (NET 700/1000/1400/500-DPC)
[hunter]
- The new metasys driver supports Meta System models: Line,
HF Millennium, HF Top Line, ECO Network, ECO, Ally HF, Megaline
[BlaXwan]
- The ippon driver now allows user-defined settings for the delay
before switching off, and the delay before powering on.
[Yuri Elizarov]
- The victronups driver is now at version 0.1.9, which adds many
instant commands: calibration control, battery and front panel tests,
and bypass control.
[Gert Lynge]
- The tripplite driver has recieved 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.
[Nicholas J Kain]
- The mge-utalk driver has been upgraded to version 0.81, which fixes
the lack of read-write variables and loss of sync on models which
don't support restoring settings.
[Arnaud Quette]
- The Micro Ferrups model RE is now supported by the bestuferrups
driver. The driver will also now read the ambient temperature and
will no longer constantly report the data as stale.
[Tim Thompson]
- The fentonups driver's init sequence has been reworked to work better
with some hardware, including a fix to the parser code.
[MLH]
- A workaround has been added to the hidups driver to avoid variables
which are stuck by calling HIDIOCINITREPORT in every poll.
[Stuart D. Gathman]
- SOLA 610 UPS hardware and others which do not support the ID command
may now be monitored by the bestups driver after forcing ID= in
ups.conf.
[Jason White]
- "pollinterval" is now available via driver.parameter for consistency.
[Arnaud Quette]
- The mge-shut and newhidups drivers, along with the supporting
hidparser/libhid code have received many updates, including lowering
USB bandwidth consumption, driver unbinding (only in Linux), code
cleanups, and more which can be seen in the ChangeLog file.
[Arnaud Quette]
- The fentonups driver now recognizes several more Megatec protocol
units:
SuperPower HP360, Hope-550 [Denis Zaika]
Unitek Alpha 1000is [Antoine Cuvellard]
- Some variables like uc_sigmask were renamed to avoid clashes with
symbols on systems like HP/UX.
- All man pages have been reworked to switch literal "-" characters to
hyphens or "\-" as appropriate.
[Shaul Karl]
- upssched's CANCEL events were broken following the change to
text-based socket messages in 1.5 and have been fixed.
[Steven Schoch]
- Calls to varargs functions with raw strings from the config files
without an intervening "%s" have been fixed in upsmon, upssched,
snmp-ups and upsd.
[Ulf Harnhammar]
---------------------------------------------------------------------------
Release notes for NUT 2.0.0 - what's new since 1.4.x:
- The new naming scheme for variables and commands (introduced in 1.4)
is now mandatory. The 1.4 tree supported both the old (STATUS) and
the new (ups.status) as a transitional release, and now that time is
over.
This means that 2.0 is generally smaller than 1.4 code, since the
interim compatibility hacks have been removed.
- New serial handling code has been added, with greatly simplified
operations. The old mess involving repeated calls to sigaction,
alarm, and read has been condensed to a select-read loop.
This change allows drivers which don't do any serial communications
at all (hidups, snmp-ups) to drop that baggage, so they are a bit
smaller when compiled.
- The drivers now recognize "chroot=' and 'user=' in the global section
of ups.conf. This means you don't have to use -r and -u when
starting upsdrvctl.
- upsmon now supports the -K argument to check for the presence of the
POWERDOWNFLAG file. If it exists and contains the magic string, then
upsmon will exit(EXIT_SUCCESS). Otherwise, it will
exit(EXIT_FAILURE).
This feature can be used to simplify shutdown scripts, since now you
don't have to keep the script in sync with the upsmon.conf.
- Many small things like signed value comparisons, int vs. size_t and
proper use of const/struct were fixed throughout the source. These
were mostly for correctness, but a few potential bugs involving very
big or very small numbers were fixed at the same time.
- The access control system in upsd.conf has been reworked and
simplified. Since access levels have become meaningless in recent
releases, the new system is just ACCEPT <acl> or REJECT <acl>.
If you are upgrading from a previous version of the software, you
will have to edit your upsd.conf to use this method. See
the UPGRADING file for more details.
- The build process now halts when make fails in one of the
subdirectories.
[Petter Reinholdtsen, Charles Lepple]
- Helper data for using upsclient via pkgconfig is now created if
pkgconfig is detected when configure runs.
[Arnaud Quette]
- The polling interval in drivers may now be set with 'pollinterval'
in ups.conf.
[Gabriel Faber]
- Blazer UPS equipment is now supported with the blazer driver.
[Phil Hutton]
- Energizer USB UPS hardware is now supported on Linux with a new
experimental driver.
[Viktor T. Toth]
- The newhidups driver has been merged as the first step towards
portable USB UPS support. This will eventually replace the old
Linux-only hidups driver. The newhidups driver is tagged
experimental since it is under active development.
[Arnaud Quette, Charles Lepple]
- The newapc driver has been renamed to apcsmart, replacing the old
driver with that name. If you used the newapc driver, be sure to
delete the old binary and fix your ups.conf.
- The apcsmart driver now supports asynchronous notification data
from the hardware, which means it can wake up as soon as something
happens. This affects the OL/OB/LB/RB data in ups.status, and
generally reduces the latency in dispatching status changes by a few
seconds.
- The apcsmart driver can now support quirky hardware which does not
provide the usual listing of valid command characters. This feature
is necessary to monitor new models like the APC CS 350 and old ones
like the Matrix 5000. It also now has sdtype=4 to handle the strange
shutdown behavior on the CS series.
- The belkin driver now works around broken firmware version 001,
avoiding a lengthy delay at startup. It also implements the shutdown
sequence differently, and should actually work on more hardware now.
- The bestups driver has been slowed down to play nicer with the
hardware, and is much more reliable as a result. Among other things,
it should always detect the UPS on the first try, meaning no more
"dot dot dot" when it starts.
- The cyberpower driver is no longer tagged experimental, and now
supports powering off the load. It also supports battery tests via
instcmds.
- Effekta MT 2000 RM hardware is now supported by the fentonups driver.
[christoph moar]
- The new safenet driver supports UPS hardware that uses the protocol
of the same name. This includes models from many manufacturers,
including Fairstone, Fenton, Gemini, Powerwell, Repotec, Soltec and
Sweex. See the README or driver.list for the full details.
[Arjen de Korte]
- The genericups driver now has type 20 to monitor the Powerware 5119
RM. See http://lists.exploits.org/ups/Oct2003/00052.html.
[Daniel Thompson]
- The belkinunv driver has been added to allow monitoring Belkin
Universal UPS hardware.
[Peter Selinger]
- Cyber Power Systems 1100AVR hardware which has a different protocol
than the existing binary type (supported by 'cyberpower') is now
supported by the experimental cyberpower1100 driver.
[Walt Holman]
- upsdrvctl now returns success or failure information in the exit
code. Any failure during a requested operation will result in a
nonzero value (specifically EXIT_FAILURE).
---------------------------------------------------------------------------
Release notes for NUT 1.4.0 - what's new since 1.2.x:
- The drivers and upsd now communicate over Unix domain sockets instead
of state files, shared memory, or state files with mmap. This change
makes many things possible, including the new dynamic variable and
command naming scheme described below.
There is a new development tool called sockdebug in the server
directory for debugging driver-server communications on the sockets.
- The old static variable scheme has been replaced by a new dynamic
implementation. Vague names have been turned into meaningful names
that fit into an organized system. UTILITY is now input.voltage.
OUTVOLT is now output.voltage.
This also applies to the names of instant commands. BTEST1 is
test.battery.start, and BTEST0 is test.battery.stop.
The old names are still supported for compatibility with older
clients. This compatibility mode will be maintained throughout
the 1.4 series, and will be gone by the release of 2.0. Users
with older clients are encouraged to upgrade their software
during this time.
- The network protocol has been expanded to handle these new names.
Older functions which only apply to the old names will continue to
be supported through the 1.4 series.
- The drivers and server (upsd) can now change their user ids and
chroot themselves with the new -u and -r arguments. This lets you
create a "chroot jail" with the bare minimum components.
This technique is used to provide a higher degree of security. If
someone exploited upsd to get a shell somehow, they would be stuck
in the jail.
- upssched now explicitly confirms reception of timer commands before
exiting. This was done to avoid a race where one process would
exit right when another one was starting. The second one would
believe its command had been handled when it had been lost.
- upslog has been reworked to use standard getopt parsing to provide
the monitoring settings. The old way of specifying arguments is
still supported for backwards compatibility.
upslog has also been changed to only parse the format string once,
rather than doing it every time through the loop. This should
provide a minuscule drop in CPU utilization.
- Usernames are now required in upsmon and upsd. This means that you
must add a username to your MONITOR lines in upsmon.conf and then
create a matching user in upsd.users.
Installations from the 1.2 era probably already use usernames, so
this mostly affects those from 1.0 and before.
- Drivers are now pinged regularly by upsd when they aren't posting
updates about the UPS status. This provides another check in the
data validation process. If upsd fails to get a response within
a few seconds, the UPS will be marked stale.
- A few minor memory leaks were discovered with valgrind and squashed.
- upsstats now reuses connections to upsd when cycling through multiple
entries in the hosts.conf. This makes things a bit faster and
avoids some of the noise in the syslog.
This only applies to entries that are adjacent. To take advantage
of this feature, you may have to rearrange them.
MONITOR ups-1@host-1 ...
MONITOR ups-1@host-2 ...
MONITOR ups-2@host-2 ...
MONITOR ups-3@host-3 ...
Connection reuse for nonadjacent entries may be considered in the
future.
- upsd now warns about insecure configuration files at startup.
These files (upsd.conf, upsd.users, and the certfile) should
only be readable by upsd. Never make them world-readable.
- The programs no longer print "shutting down" when they are just
exiting. This was changed to avoid confusion about the term, since
"shutting down" has a special meaning in UPS software.
- Signal handlers no longer do any significant amount of work. Some of
the programs used to do numerous things in there, raising concerns
about reentrancy. They now set flags and allow the main loop to do
the actual work from there.
- A bug in upsmon where NOTIFYFLAG settings could be ignored was fixed.
- Group handling has been changed. configure no longer accepts
--with-group, and the programs no longer setgid() to a hardcoded
value. They now setgid() to the primary group of whatever the
user value may be.
This may be compiled in with --with-user as before, and many programs
accept -u to override it at runtime.
- The state path is no longer created during 'make install'. Users
are now expected to create it themselves. This removes a lot of
evil complexity from the build and install sequences.
- upsd no longer implements the DROP access command, as it
could confuse the clients by getting them out of sync. DROP is now
implemented as DENY, which sends an error message. If you use DROP,
you should change it to DENY rather than relying on this
compatibility measure.
- The belkin driver no longer reports OFF and OL at the same time.
- The bestups driver no longer sleeps during polls, which makes it
more responsive to things like instant commands.
- The cyberpower driver now has much better hardware detection code
and no longer freezes at startup under some conditions. It also now
supports the shutdown function. Instant commands for shutdowns and
battery tests were also added.
- The dummyups testing driver has been removed. The dummycons testing
driver can do everything that dummyups once did and much more.
dummycons is also now built by default for easier testing.
- The newapc driver has been reworked to take advantage of the new
internal driver state functions. Some variables without an obvious
purpose were dropped.
- The newapc driver now sends all five bytes when using sdtype 1.
Previously it didn't send the entire string, and it didn't work.
[Don Lewis]
- The hidups driver has been expanded to allow for setting variables,
a shutdown sequence, and more.
[Arnaud Quette]
- The mge-utalk driver had trouble establishing communications in
some cases due to the RTS line being set. This has been fixed.
The mge-shut driver has been added to the tree, and has replaced
the older mge-ellipse driver.
[Arnaud Quette, Philippe Marzouk]
- Outlet-level control has been defined in the variable tree, and will
be added to drivers where the hardware supports it. This can be
used to shut down some components earlier than others to prolong
your runtime on battery.
This is supported in the mge-shut driver now, and may show up in
others before long.
[Arnaud Quette]
- KIN-2200AP hardware is now recognized by the powercom driver.
This change may also support other KIN-xxxxAP equipment.
[Preston A. Elder]
- The 1.1kVA UPS is now supported by the bestuferrups driver. This
driver was also changed to allow easy addition of more models
in the future.
[Bob Apodaca]
- The fentonups driver can now handle devices which implement the
"I" detection differently, and now supports the Giant/WELI 500
as a result.
[Joon Guillen]
- The serial number of the UPS being monitored can now be specified
with serial= in ups.conf in the genericups driver.
[Shaul Karl]
- The newapc driver now sends ESC to break out of menus when the
initial detection fails. Some new APC models have interactive menus
on the serial port, and the driver couldn't handle them before.
- The snmp-ups driver now reports ambient temperature and humidity
data for APC equipment. It also now supports the shutdown.reboot and
shutdown.reboot.graceful commands.
[Dmitry Frolov]
- The list of supported variables and commands in the snmp-ups driver
has been expanded.
[Arnaud Quette, J.W. Hoogervorst]
- Various drivers now report bypass mode with the BYP status word.
[Arnaud Quette]
- Energy Sistem equipment is now supported with the esupssmart driver.
[Antonio Trujillo Coronado]
- The Tripp-Lite SU series (SmartOnline) is supported with the new
tripplitesu driver.
[Allan Hessenflow]
- The HP PowerTrust A2994A is now recognized by the hp driver.
[Jan Sporbeck]
- Many drivers were cleaned up to perform basic sanity checks on the
status data before using it.
- An explicit cleanup function has been added to the driver core to
ensure that all dynamic resources are freed before exiting. This
is part of the larger process to check for memory leaks and other
bad things.
[Arnaud Quette]
- upsd now provides variable descriptions from an auxiliary file.
This file is optional, which allows for a smaller memory footprint.
It can also be edited for localization or other customizations.
- upsimage and upsstats can now render BATTVOLT data.
[Andrew R. Ghali]
- String handling has been cleaned up throughout the tree. Calls to
functions like strcpy and strcat were either replaced with other
(range-checking) functions or were rewritten to avoid it.
- Many compile-time defaults may now be overridden at runtime. In
the environment NUT_CONFPATH and NUT_STATEPATH may be used.
upsdrvctl has been changed to execve to pass these along to the
drivers. ups.conf now supports driverpath=, and upsd.conf supports
DATAPATH.
[Bryan Henderson]
- The configure --with-gd switches now actually do something useful
when gd has been installed outside the default search directories.
[Patrik Schindler]
- The inline keyword is now handled properly on systems which do not
support it or have it specified as another name. This was breaking
compiles on some systems.
[Petter Reinholdtsen]
---------------------------------------------------------------------------
Release notes for NUT 1.2.2 - what's new since 1.2.1:
- The snmp-ups driver has been upgraded and expanded. It now supports
multiple MIBs, meaning it can handle RFC 1628, APCC, and MGE
equipment. You can pick the right one with "mibs=" in ups.conf.
Support for setting variable and instant commands is also available.
[Arnaud Quette and Dmitry Frolov]
- The powernet driver has been upgraded. It now supports more
variables, has cleaner logging, and may now be considered stable.
[Dmitry Frolov]
- The hidups driver now supports physical port IDs. This avoids most
of the problems where the hiddev* names can jump around too easily.
It will now stay in the same place as long as you keep it plugged
into the same physical port. See the ChangeLog file for more details.
[David Brownell]
- The hidups driver now also supports the MFR variable on APC
Back-UPS ES equipment.
[Jonathan A. Davis]
- The sms driver has been updated to version 0.70.
[Marcio Gomes]
- The bestups driver now recognizes Best Power Axxium Rackmount
equipment.
[Ales Casar]
- The liebert driver now uses O_NONBLOCK, and should now work
consistently on OpenBSD as a result.
[Alex Cichowski]
- The liebert driver also now uses debouncing logic on the status
lines. It was possible to get false readings that would start a
shutdown or just annoy users with excessive onbatt/online notify
messages. The new code forces the status to settle down for 3 polls
before accepting the new value.
This means that very short power events may not be detected. The
alternative is having your machine shut down just because it decided
to wiggle over to OB LB for a few seconds.
- upsmon has had the disconnect logic fixed so the "communications
lost" (COMMBAD) notify will actually go out when the connection
fails.
[Steve Monett]
- upssched now uses a lock file to prevent a race where two could
start at the same time. The second upssched would "win", and the
first one would be unreachable. This had the side-effect of not
being able to cancel timers on the first one.
If you use upssched, you must define the LOCKFN directive when
upgrading to this version, or it will not work.
[Gaspar Bakos]
- The packaging and scripts for Red Hat systems have been updated.
[Antonino Albanese]
- upsd is now a bit more lenient about access levels in the
'numlogins' check, which is what caused the problem in upsmon
(next item).
- upsmon no longer gets stuck in slavesync() when upsd is configured
to drop certain queries. This usually happened at the worst
possible time: in the middle of a shutdown.
[John David Garza]
- The upsclient functions now do more sanity checking on data from
upsd so a short read won't return garbage to the callers.
- upsset now works properly with ENUM/VARTYPE values for multiple
UPSes on a single upsd.
[Dmitry Frolov]
- Various portability fixes for building on SGI were applied.
[Andrea Suatoni]
- upsd no longer tries to reference a deleted client structure if the
client disconnects at the wrong time. Previously, it tried to use
that pointer after the sendback() function had already failed on
write and deleted the client. This could cause upsd to segfault
depending on what areas were accessed.
[Patrik Schindler]
---------------------------------------------------------------------------
Release notes for NUT 1.2.1 - what's new since 1.2.0:
- The sms driver is back, with support for Microlink Manager III
hardware. [Marcio Gomes]
- Fideltronik Ares Series hardware is now supported as genericups type
19. [Tomek Orzechowski and Arkadiusz Mikiewicz]
- The drivers no longer silently drop instant commands or set commands
from upsd that happen to get fragmented in transit.
[linux@horizon.com]
- The old multilink driver is back with a new name: liebert. It
supports Liebert UPStation GXE hardware with the contact-closure
cable. This is currently an experimental driver as there is no
way to power down the load.
- configure now picks up the right flags for gd automatically if gd
2.0.8 or higher is installed. This greatly simplifies the CGI build
process for most users.
- Shutdowns on FreeBSD using the genericups driver should work again.
[Petri Riihikallio]
---------------------------------------------------------------------------

659
README Normal file
View file

@ -0,0 +1,659 @@
=================================
Network UPS Tools Documentation
=================================
:Info: Program support page: <http://www.networkupstools.org/>
:Author: Arnaud Quette <aquette.dev@gmail.com> and others, see AUTHORS file.
:Copyright: Released under the GNU GPL - see COPYING for details.
Mailing list details: http://alioth.debian.org/mail/?group_id=30602
.. contents::
===========
Description
===========
Network UPS Tools is a collection of programs which provide a common
interface for monitoring and administering UPS and PDU hardware. NUT comes in
two flavors: the "classic" and the "HAL enabled" one.
The "classic" flavor
--------------------
It is the standard installation that uses a layered approach to connect
all of the NUT parts.
Drivers are provided for a wide assortment of equipment. They
understand the specific language of each device and map it back to a
compatibility layer. This means both an expensive "smart" protocol UPS
and a simple "power strip" model can be handled transparently.
This information is cached by the network server ``upsd``, which then
answers queries from the clients. upsd contains a number of access
control features to limit the abilities of the clients. Only authorized
hosts may monitor or control your hardware if you wish. Since the
notion of monitoring over the network is built into the software, you
can hang many systems off one large UPS and they will all shut down
together. You can also use NUT to power on, off or cycle your data centers
nodes, individually or globally through PDUs outlets.
Clients such as upsmon check on the status of the hardware and do things
when necessary. The most important task is shutting down the operating
system cleanly before the UPS runs out of power. Other programs are
also provided to log UPS status regularly, monitor status through your
web browser, and more.
The "HAL enabled" flavor
------------------------
This one is intended for use:
- with supported USB UPS,
- on HAL enabled systems (Linux, FreeBSD, Sun Solaris),
- on HAL enabled desktops (Gnome and possibly KDE)
Using this approach, you don't have to configure NUT files, nor to
manually start components, nor to install a specific NUT client.
Upon plugging your USB UPS, the right driver will be automatically
launched, and the according Power Manager GUI will pop up.
Note that this feature is still beta and incomplete. But it
represents a major evolution, and a huge user experience improvement!
For more information, refer to INSTALL and docs/nut-hal.txt.
==========
Installing
==========
If you are installing these programs for the first time, go read the
INSTALL file to find out how to do that. This document contains more
information on what all of this stuff does.
=========
Upgrading
=========
When upgrading from an older version, always check the UPGRADING file to
see what may have changed. Compatibility issues and other changes will
be listed there to ease the process.
=============
Documentation
=============
This file gives an overview of the software. You should read the man
pages, included example configuration files, and auxiliary documentation
for the parts that you intend to use.
===================
Network Information
===================
These programs are designed to share information over the network. In
the examples below, ``localhost`` is used as the hostname. This can also
be an IP address or a fully qualified domain name. You can specify a
port number if your upsd process runs on another port.
In the case of the program ``upsc``, to view the variables on the UPS called
sparky on the ``upsd`` server running on the local machine, you'd do this::
/usr/local/ups/bin/upsc sparky@localhost
The default port number is 3493. You can change this with
"configure --with-port" at compile-time. To make a client talk to upsd
on a specific port, add it after the hostname with a colon, like this::
/usr/local/ups/bin/upsc sparky@localhost:1234
This is handy when you have a mixed environment and some of the systems
are on different ports.
The general form for UPS identifiers is this::
<upsname>[@<hostname>[:<port>]]
Keep this in mind when viewing the examples below.
========
Manifest
========
This package is broken down into several categories:
- *drivers* - These programs talk directly to your UPS hardware.
- *server* - upsd serves data from the drivers to the network.
- *clients* - They talk to upsd and do things with the status data.
- *cgi-bin* - Special class of clients that you can use with your web server.
=======
Drivers
=======
These programs provide support for specific UPS models. They understand
the protocols and port specifications which define status information
and convert it to a form that upsd can understand.
To configure drivers, edit ups.conf. For this example, we'll have a UPS
called "sparky" that uses the apcsmart driver and is connected to
``/dev/ttyS1``. That's the second serial port on most Linux-based systems.
The entry in ``ups.conf`` looks like this::
[sparky]
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::
/usr/local/ups/bin/upsdrvctl start
/usr/local/ups/bin/upsdrvctl stop
However, you can also just start or stop one by adding its name::
/usr/local/ups/bin/upsdrvctl start sparky
/usr/local/ups/bin/upsdrvctl stop sparky
To get the driver name for your device, refer to the below section
called "HARDWARE SUPPORT TABLE".
Extra Settings
--------------
Some drivers may require additional settings to properly communicate
with your hardware. If it doesn't detect your UPS by default, check the
driver's man page or help (-h) to see which options are available.
For example, the apcsmart driver allows setting "cable" to "940-0095B".
To use this feature, just add another line to your ups.conf section for
that UPS::
[sparky]
driver = apcsmart
port = /dev/ttyS1
cable = 940-0095B
Hardware Support Table
----------------------
The NUT Hardware support table is available in the source directory:
nut-X.Y.Z/data/driver.list
This one should also be distributed with your favorite packages.
For example, it is available on Debian systems as:
/usr/share/nut/driver.list
For another take on this list, try the web page:
http://random.networkupstools.org/compat/
If your driver has vanished, see the FAQ and UPGRADING files.
Generic UPS Driver
------------------
The ``genericups`` driver will support many models that use the same basic
principle to communicate with the computer. This is known as "contact
closure", and basically involves raising or lowering signals to indicate
power status.
This type of UPS tends to be cheaper, and only provides the very simplest
data about power and battery status. Advanced features like battery
charge readings and such require a "smart" UPS and a driver which
supports it.
See the genericups(8) man page for more information.
There is also a document called contact-closure.txt included with the
source distribution that contains information on this kind of hardware
and details on adding additional types to the genericups driver.
UPS Shutdowns
-------------
upsdrvctl can also shut down (power down) all of your UPS hardware.
**WARNING:** if you play around with this command, expect your filesystems
to die. Don't power off your computers unless they're ready for it::
/usr/local/ups/bin/upsdrvctl shutdown
/usr/local/ups/bin/upsdrvctl shutdown sparky
You should read the shutdown.txt file in the docs subdirectory to
learn more about when to use this feature. If called at the wrong time,
you may cause data loss by turning off a system with a filesystem
mounted read-write.
==============
Network Server
==============
``upsd`` is responsible for passing data from the drivers to the client
programs via the network. It should be run immediately after ``upsdrvctl``
in your system's startup scripts.
``upsd`` should be kept running whenever possible, as it is the only source
of status information for the monitoring clients like ``upsmon``.
======
upsmon
======
``upsmon`` provides the essential feature that you expect to find in UPS
monitoring software: safe shutdowns when the power fails.
In the layered scheme of NUT software, it is a client. It has this
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 three possible types:
- Master
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.
If your UPS is plugged directly into a system's serial port,
the upsmon on that system should define that UPS as a master.
- Slave
This UPS supplies power to the system running upsmon, but
this system can't shut it down directly. This system will
shut down the operating system before the master turns off the
power.
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.
- Monitor-only
This UPS will still generate notifications about status
changes (on battery, on line, etc.) but no shutdowns of the
local system result from critical situations on that UPS.
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.
Additional Information
----------------------
More information on configuring upsmon can be found in these places:
- The man page - upsmon(8)
- big-servers.txt in the docs subdirectory
- shutdown.txt in the docs subdirectory
- The stock upsmon.conf that comes with the package
=======
Clients
=======
Clients talk to upsd over the network and do useful things with the data
from the drivers. There are tools for command line access, and a few
special clients which can be run through your web server as CGI
programs.
For more details on specific programs, refer to their man pages.
upsc
----
upsc is a simple client that will display the values of variables known
to upsd and your UPS drivers. It will list every variable by default,
or just one if you specify an additional argument. This can be useful
in shell scripts for monitoring something without writing your own
network code.
upsc is a quick way to find out if your driver(s) and upsd are working
together properly. Just run upsc <ups> to see what's going on, i.e.::
morbo:~$ upsc su700@localhost
ambient.humidity: 035.6
ambient.humidity.alarm.maximum: NO,NO
ambient.humidity.alarm.minimum: NO,NO
ambient.temperature: 25.14
[ and so on ]
If you are interested in writing a simple client that monitors upsd,
the source code for upsc is a good way to learn about using the
upsclient functions.
See the upsc(8) man page for more information.
upslog
------
upslog will write status information from upsd to a file at set
intervals. You can use this to generate graphs or reports with other
programs such as gnuplot.
upsrw
-----
upsrw allows you to display and change the read/write variables in your
UPS hardware. Not all devices or drivers implement this, so this may
not have any effect on your system.
A driver that supports read/write variables will give results like this::
$ upsrw su700@localhost
( many skipped )
[ups.test.interval]
Interval between self tests
Type: ENUM
Option: "1209600"
Option: "604800" SELECTED
Option: "0"
( more skipped )
On the other hand, one that doesn't support them won't print anything::
$ upsrw fenton@gearbox
( nothing )
upsrw requires administrator powers to change settings in the hardware.
Refer to upsd.users(5) for information on defining users in upsd.
upscmd
------
Some UPS hardware and drivers support the notion of an instant command -
a feature such as starting a battery test, or powering off the load.
You can use upscmd to list or invoke instant commands if your
hardware/drivers support them.
Use the -l command to list them, like this::
$ upscmd -l su700@localhost
Instant commands supported on UPS [su700@localhost]:
load.on - Turn on the load immediately
test.panel.start - Start testing the UPS panel
calibrate.start - Start run time calibration
calibrate.stop - Stop run time calibration
[ snip ]
upscmd requires administrator powers to start instant commands.
To define users and passwords in upsd, see upsd.users(5).
============
CGI Programs
============
The CGI programs are clients that run through your web server. They
allow you to see UPS status and perform certain administrative commands
from any web browser. Javascript and cookies are not required.
These programs are not installed or compiled by default. To compile
and install them, first run 'configure --with-cgi', then do 'make' and
'make install'. If you receive errors about "gd" during configure, go
get it and install it before continuing.
You can get the source here:
http://www.boutell.com/gd/
In the event that you need libpng or zlib in order to compile gd,
they can be found at these URLs:
http://www.libpng.org/pub/png/pngcode.html
http://www.gzip.org/zlib/
Access Restrictions
-------------------
The CGI programs use hosts.conf to see if they are allowed to talk to a
host. This keeps malicious visitors from creating queries from your web
server to random hosts on the Internet.
If you get error messages that say "Access to that host is not
authorized", you're probably missing an entry in your hosts.conf.
upsstats
--------
upsstats generates web pages from HTML templates, and plugs in status
information in the right places. It looks like a distant relative of
APC's old Powerchute interface. You can use it to monitor several
systems or just focus on one.
It also can generate IMG references to upsimage.
upsimage
--------
This is usually called by upsstats via IMG SRC tags to draw either the
utility or outgoing voltage, battery charge percent, or load percent.
upsset
------
upsset provides several useful administration functions through a web
interface. You can use upsset to kick off instant commands on your UPS
hardware like running a battery test. You can also use it to change
variables in your UPS that accept user-specified values.
Essentially, upsset provides the functions of upsrw and upscmd, but
with a happy pointy-clicky interface.
upsset will not run until you convince it that you have secured your
system. You *must* secure your CGI path so that random interlopers
can't run this program remotely. See the upsset.conf file. Once you
have secured the directory, you can enable this program in that
configuration file. It is not active by default.
=====================
Support / Help / etc.
=====================
The main URL:
http://www.networkupstools.org/
There is also a mailing list for general queries and discussion about
this software called nut-upsuser. It typically moves around 50-100 messages
per month at the time of this writing. To join, go to the below address and
subscribe to the desired list.
Finally, there is a developer list called nut-upsdev. This is not
an install help list, and any such mails probably will be ignored.
The mailing lists are archived on the web:
http://alioth.debian.org/mail/?group_id=30602
Try running some searches against the archives. Many times, problems have
already been answered by someone else. Currently, there is no internal
search engine, so you will have to try with a search engine like Google.
There is more documentation in the docs/ directory within the source
tree. Be sure to read through the files in there (especially the
FAQ) before mailing the list for help. Many times the questions have
already been answered in the files which are right in front of you.
===================================
Making your own clients (upsclient)
===================================
The upsclient.a library can be linked into other programs to give access
to upsd and UPS status information. Clients like upsc are provided as
examples of how to retrieve data using the upsclient functions. Other
programs not included in this package may also use this library, as wmnut.
This library file and the associated header files are not installed by
default. You must './configure --with-lib' to enable building and
installing these files. The libraries can then be build and installed
with 'make' and 'make install' as usual. This must be done before
building other (non-NUT) programs which depend on them.
To obtain the right compilation and link flags, two helpers are provided:
one for platform providing pkg-config, and the other (libupsclient-config)
for platform not providing pkg-config.
=================
Version Numbering
=================
The version numbers work like this: if the middle number is odd, it's a
development tree, otherwise it is the stable tree.
The past stable trees were 1.0, 1.2, 1.4 and 2.0, with the latest stable tree
designated 2.2. The development trees were 1.1, 1.3, 1.5 and 2.1.
The jump to 2.2 is mostly due to the large changes to the features list.
There have also been a number of architectural changes which may not be
noticeable to most users.
====================================
Backwards and Forwards Compatibility
====================================
The old network code spans a range from about 0.41.1 when TCP support
was introduced up to the recent 1.4 series. It used variable names
like STATUS, UTILITY, and LOADPCT. Many of these names go back to the
earliest prototypes of this software from 1997. At that point there
was no way to know that so many drivers would come along and introduce
so many new variables and commands. The resulting mess grew out of
control over the years.
During the 1.3 development cycle, all variables and instant commands
were renamed to fit into a tree-like structure. There are major groups,
like input, output and battery. Members of those groups have been
arranged to make sense - input.voltage and output.voltage compliment
each other. The old names were UTILITY and OUTVOLT. The benefits in
this change are obvious.
The 1.4 clients can talk to either type of server, and can handle either
naming scheme. 1.4 servers have a compatibility mode where they can
answer queries for both names, even though the drivers are internally
using the new format.
When 1.4 clients talk to 1.4 or 2.0 (or more recent) servers, they will
use the new names.
Here's a table to make it easier to visualize:
+--------+------------------------+
| | Server |
+--------+-----+-----+-----+------+
| Client | 1.0 | 1.2 | 1.4 | 2.0+ |
+========+=====+=====+=====+======+
| 1.0 | yes | yes | yes | no |
+--------+-----+-----+-----+------+
| 1.2 | yes | yes | yes | no |
+--------+-----+-----+-----+------+
| 1.4 | yes | yes | yes | yes |
+--------+-----+-----+-----+------+
| 2.0 | no | no | yes | yes |
+--------+-----+-----+-----+------+
Version 2.0 (and more recent) does not contain backwards compatibility for
the old protocol and variable/command names. As a result, 2.0 clients can't
talk to anything older than a 1.4 server. If you ask a 2.0 client to
fetch "STATUS", it will fail. You'll have to ask for "ups.status"
instead.
Authors of separate monitoring programs should have used the 1.4 series
to write support for the new variables and command names. Client
software can easily support both versions as long as they like. If upsd
returns 'ERR UNKNOWN-COMMAND' to a GET request, you need to use REQ.
==========================
Hacking / Development Info
==========================
Additional documentation can be found in the docs subdirectory.
Information on creating new drivers can be found in new-drivers.txt.
Also be sure to look at skel.c and main.c. All drivers are just
collections of support functions built around a common core, so most of
the dull housekeeping work has been handled for you.
Information on the NUT variables naming can be found in new-names.txt.
Information on the architecture and how it all fits together is in the
design.txt file. In short, there's a lot more documentation out there.
Also be sure to read developers.txt, as it explains a lot about the
tree, including some of the functions that are provided for your use.
================================
Acknowledgements / Contributions
================================
MGE UPS SYSTEMS provided extensive technical documents for their UPS product
line, along with many units for development of NUT-related projects. The
company also sponsored and later hired Arnaud Quette to further officially
support these efforts.
Several drivers such as mge-utalk, mge-shut, snmp-ups, hidups, and usbhid-ups
are the result of this collaboration, in addition to the WMNut, MGE HID Parser
the libhid projects, .... The features page has improved artwork thanks to Luc
and Arnaud of MGE. Other client projects such as KNutClient and ups-monitor
have also received assistance.
The master NUT site and several related projects are hosted on MGE's equipment
at no cost to the project.
More information on their open source support can be found on their web site:
http://opensource.mgeups.com/contrib.htm
Fenton Technologies contributed a PowerPal 660 to the project. Their open
stance and quick responses to technical inquiries are appreciated for
making the development of the fentonups driver possible.
Bo Kersey of VirCIO (http://www.vircio.com) provided a Best Power
Fortress 750 to facilitate the bestups driver.
Invensys Energy Systems provided the SOLA/Best "Phoenixtec" protocol
document currently residing at the following URL:
http://random.networkupstools.org/protocols/sola.html
PowerKinetics technical support provided documentation on their MiniCOL
protocol, which is archived in the NUT protocol library online:
http://random.networkupstools.org/protocols/minicol/
Cyber Power Systems contributed a 700AVR model for testing and driver
development.
Liebert Corporation supplied serial test boxes and a UPStation GXT2
with the Web/SNMP card for development of the liebert driver and
expansion of the existing snmp-ups driver.

373
UPGRADING Normal file
View file

@ -0,0 +1,373 @@
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.4.2 to 2.4.3:
- nothing that affects upgraded systems.
---------------------------------------------------------------------------
Changes from 2.4.1 to 2.4.2:
- The default subdriver for the blazer_usb driver USB id 06da:0003 has
changed. If you use such a device and it is no longer working with this
driver, override the 'subdriver' default in 'ups.conf' (see man 8 blazer).
- NUT ACL and the allowfrom mechanism has been replaced in 2.4.0 by the LISTEN
directive and tcp-wrappers respectively. This information was missing
below, so a double note has been added.
---------------------------------------------------------------------------
Changes from 2.4.0 to 2.4.1:
- nothing that affects upgraded systems.
---------------------------------------------------------------------------
Changes from 2.2.2 to 2.4.0:
- The nut.conf file has been introduced to standardize startup configuration
across the various systems.
- The cpsups and nitram drivers have been replaced by the powerpanel driver,
and removed from the tree. The cyberpower driver may suffer the same in the
future.
- The al175 and energizerups drivers have been removed from the tree, since
these were tagged broken for a long time.
- Developers of external client application using libupsclient must rename
their "UPSCONN" client structure to "UPSCONN_t".
- The upsd server will now disconnect clients that remain silent for more than
60 seconds.
- The files under scripts/python/client are distributed under GPL 3+, whereas
the rest of the files are distributed under GPL 2+. Refer to COPYING for more
information.
- The generated udev rules file has been renamed with dash only, no underscore
anymore (ie 52-nut-usbups.rules instead of 52_nut-usbups.rules)
- (Note: this has been missed at release time): The NUT internal network access
control (ACL using ACCEPT / REJECT in upsd.conf) has been replaced by
the LISTEN directive. This can also be complemented by tcp-wrappers.
Refer to upsd and upsd.conf manual pages for more information.
---------------------------------------------------------------------------
Changes from 2.2.1 to 2.2.2:
- The configure option "--with-lib" has been replaced by "--with-dev".
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
"--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
encouraged to test this feature by calling "upsmon -c fsd" and
report any issue on the NUT mailing lists.
---------------------------------------------------------------------------
Changes from 2.2.0 to 2.2.1:
- nothing that affects upgraded systems.
(The below message is repetead 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.
---------------------------------------------------------------------------
Changes from 2.0.5 to 2.2.0:
- users of the newhidups driver are advised that the driver name has changed
to usbhid-ups.
- users of the hidups driver must switch to usbhid-ups.
- users of the following drivers (powermust, blazer, fentonups, mustek,
esupssmart, ippon, sms) must switch to megatec, which replaces
all these drivers. Please refer to doc/megatec.txt for details.
- users of the mge-shut driver are encouraged to test newmge-shut, which
is an alternate driver scheduled to replace mge-shut,
- users of the cpsups driver are encouraged to switch to powerpanel which
is scheduled to replace cpsups,
- packagers will have to rework the whole nut packaging due to the
major changes in the build system (completely modified, and now using
automake). Refer to packaging/debian/ for an example of migration.
- specifying '-a <id>' is now mandatory when starting a driver manually,
ie not using upsdrvctl.
- Developers of external client application using libupsclient are
encouraged to rename the "UPSCONN" client structure to "UPSCONN_t"
since the former will disapear by the release of NUT 2.4.
---------------------------------------------------------------------------
Changes from 2.0.4 to 2.0.5:
- users of the newhidups driver: the driver is now more strict about
refusing to connect to unknown devices. If your device was
previously supported, but fails to be recognized now, add
'productid=XXXX' to ups.conf. Please report the device to the NUT
developer's mailing list.
---------------------------------------------------------------------------
Changes from 2.0.3 to 2.0.4:
- nothing that affects upgraded systems.
- users of the following drivers (powermust, blazer, fentonups, mustek,
esupssmart, ippon, sms, masterguard) are encouraged to switch to megatec,
which should replace all these drivers by nut 2.2. For more information,
please refer to doc/megatec.txt
---------------------------------------------------------------------------
Changes from 2.0.2 to 2.0.3:
- nothing that affects upgraded systems.
- hidups users are encouraged to switch to newhidups, as hidups will be
removed by nut 2.2.
---------------------------------------------------------------------------
Changes from 2.0.1 to 2.0.2:
- The newhidups driver, which is the long run USB support approach,
needs hotplug files installed to setup the right permissions on
device file to operate. Check newhidups manual page for more information.
---------------------------------------------------------------------------
Changes from 2.0.0 to 2.0.1:
- The cyberpower1100 driver is now called cpsups since it supports
more than just one model. If you use this driver, be sure to remove
the old binary and update your ups.conf 'driver=' setting with the
new name.
- The upsstats.html template page has been changed slightly to reflect
better HTML compliance, so you may want to update your installed copy
accordingly. If you've customized your file, don't just copy the new
one over it, or your changes will be lost!
---------------------------------------------------------------------------
Changes from 1.4.0 to 2.0.0:
- The sample config files are no longer installed by default. If you
want to install them, use 'make install-conf' for the main programs,
and 'make install-cgi-conf' for the CGI programs.
- ACCESS is no longer supported in upsd.conf. Use ACCEPT and REJECT.
Old way:
ACCESS grant all adminbox
ACCESS grant all webserver
ACCESS deny all all
New way:
ACCEPT adminbox
ACCEPT webserver
REJECT all
Note that ACCEPT and REJECT can take multiple arguments, so this
will also work:
ACCEPT adminbox webserver
REJECT all
- The drivers no longer support sddelay in ups.conf or -d on the
command line. If you need a delay after calling 'upsdrvctl
shutdown', add a call to sleep in your shutdown script.
- The templates used by upsstats have changed considerably to reflect
the new variable names. If you use upsstats, you will need to
install new copies or edit your existing files to use the new names.
- Nobody needed UDP mode, so it has been removed. The only users
seemed to be a few people like me with ancient asapm-ups binaries.
If you really want to run asapm-ups again, bug me for the new patch
which makes it work with upsclient.
- 'make install-misc' is now 'make install-lib'. The misc directory
has been gone for a long time, and the target was ambiguous.
- The newapc driver has been renamed to apcsmart. If you previously
used newapc, make sure you delete the old binary and fix your
ups.conf. Otherwise, you may run the old driver from 1.4.
---------------------------------------------------------------------------
Changes from 1.2.2 to 1.4.0:
- The clients no longer support the notion of a "default UPS" when
communicating with newer versions of upsd. If you leave off a UPS
name, they will fall back on compatibility mode and will use the
old variable and command names.
That is, "upsc localhost" will give you things like STATUS, and you
have to do "upsc myups@localhost" to get the new ones like
ups.status.
The old variable names and default UPS mode will be supported
throughout the 1.4 series to allow users to convert to the new
style. This support will be formally dropped in 2.0.
- upsmon is part of the "no default upsname" change. You must change
the MONITOR directives in your upsmon.conf if you were using this
technique before.
Old way:
MONITOR bigserver 1 monuser password master
New way:
MONITOR myups@bigserver 1 monuser password master
Just look at the top of ups.conf on 'bigserver' to figure out what
the first UPS is called, and stick it and a @ on that MONITOR line.
- upsrw's appearance has changed to avoid wrapping when displaying
the new longer variable names and descriptions. It still displays
the old format when talking to an older upsd.
To see the difference, try "upsrw localhost" and then compare it to
"upsrw myups@localhost", assuming a new version of upsd is running
on localhost.
- upslog now uses the new variable names in the default format
string. It will still monitor the old variable names for backwards
compatibility, but you will have to specify the format string
explicitly.
- 'make install' no longer creates the state path. Instructions for
creating it properly have been added to the INSTALL file.
Technically, this only affects packagers, since this is the
UPGRADING file and normal users should already have a state path.
If you are a packager, you will need to add the right mkdir + chown +
chmod magic to your install process to keep things working.
This also means that you no longer need any special permissions to
bundle this software into a package. The installer no longer
requires root now that the chown is gone.
- configure --with-group no longer does anything useful. The programs
which will drop permissions support "-u <user>", and will pick up
the group id based on the values in /etc/passwd for that user name.
configure --with-user still works as before, and provides the default
value if you don't specify another one with -u.
- The "DROP" action in upsd.conf now behaves a little differently.
It still causes new TCP connections to be closed without reading
from the socket, and still causes UDP datagrams to be ignored.
The only difference is that commands that are denied after the
remote host connects will now generate an error message. Previously,
upsd would just ignore them, and the clients could get out of sync.
DENY also has been changed slightly to silently ignore UDP packets.
Essentially, DROP and DENY are now the same thing. If you use DROP
anywhere, you should change to DENY before it goes away in the future.
- upsmon now requires a username on the MONITOR lines. If you have an
older installation from the 1.x era or earlier, you probably need
to convert them.
Old way: MONITOR ups@mybox 1 mypass master
New way: MONITOR ups@mybox 1 username mypass master
You will also have to add a [username] section to the upsd.users
with a matching password, an allowfrom value, and "upsmon master" or
"upsmon slave".
If upsmon says the login failed due to "username required" or fails to
start, saying "Unable to use old-style MONITOR line without a username",
then you're still using the old method.
---------------------------------------------------------------------------
Changes from 1.2.1 to 1.2.2:
- upssched.conf now requires the LOCKFN directive to prevent races when
handling two events that happen at nearly the same time.
If you use upssched, you must add this to your upssched.conf or it
will fail to run.
---------------------------------------------------------------------------
Changes from 1.0.0 to 1.2.0:
- upsct is gone. upsc now uses the new upsclient library which is
TCP only, so there is no need for a separate client for TCP polling.
- upsct2 has been renamed to upsrw since the name was already
ambiguous and it looked even more out of place with upsct gone.
- The multimon.cgi behavior has been absorbed into upsstats.cgi.
- Calling upsstats.cgi with no arguments will make it render
the template file called upsstats.html in your confpath. The default
version of this file looks a lot like multimon, but is flexible.
You will have to copy this file from upsstats.html.sample to
upsstats.html the first time you install this version.
- Calling upsstats.cgi with host= set will still render a single status
page as before, but the markup for that page now comes from
upsstats-single.html. This is also a template and may be
reconfigured to suit your needs. It must also be copied over from
the .sample filename the first time.
- upsmon can now send a username when authenticating to upsd. It is
recommended that you change to this mode, as the old host-based
authentication is clunky and eventually will be removed.
Old way:
MONITOR myups@bigserver 1 blah master
New way:
MONITOR myups@bigserver 1 monmaster blah master
Note that the username has been inserted between the power value and
the password. When switching to this method, be sure to add a user
to upsd.users, i.e.:
[monmaster]
password = blah
allowfrom = localhost
upsmon master
You still need to give the upsmon host(s) at least "monitor" access,
so don't delete those old ACCESS lines in your upsd.conf. Just
lower the access level and remove the password.
Old way:
ACCESS grant master localhost blah
New way:
ACCESS grant monitor localhost
- The old upsfetch "library" (used loosely) has been replaced by
upsclient. This will be installed if you do "make install-misc",
but it goes into $(prefix)/lib and $(prefix)/include by default.
The upsclient interface is not compatible with upsfetch. Old
accessory programs which linked to upsfetch will have to be updated
to work with upsclient instead.
Existing binaries that were linked against upsfetch will still work
since the network protocol used by upsd has not changed.
- SET and INSTCMD no longer work via host-level authentication. This
is only a meaningful change if you are using very old versions of
upscmd/upsct2/upsset.cgi, or if you're talking to upsd directly.
You must now set a USERNAME first, and authentication will occur
through upsd.users as a result.
This means that the "manager" level in upsd.conf ACCESS directives
is no longer meaningful, and you should remove them.
- INSTALLROOT is no longer available for redirecting 'make install' -
use DESTDIR instead.
- Makefile targets have been reworked to allow fine-grained control
over what happens at install-time. 'make install' and 'make
install-cgi' still do everything, but you can call subsets instead
if necessary. See ChangeLog.

1155
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load diff

53
clients/Makefile.am Normal file
View file

@ -0,0 +1,53 @@
# Network UPS Tools: clients
# by default, link programs in this directory with libcommon.a
LDADD = ../common/libcommon.a libupsclient.la $(NETLIBS)
if WITH_SSL
LDADD += $(LIBSSL_LDFLAGS)
endif
# Avoid per-target CFLAGS, because this will prevent re-use of object
# files. In any case, CFLAGS are only -I options, so there is no harm,
# but only add them if we really use the target.
AM_CFLAGS = -I$(top_srcdir)/include
if WITH_SSL
AM_CFLAGS += $(LIBSSL_CFLAGS)
endif
if WITH_CGI
AM_CFLAGS += $(LIBGD_CFLAGS)
endif
bin_PROGRAMS = upsc upslog upsrw upscmd
dist_bin_SCRIPTS = upssched-cmd
sbin_PROGRAMS = upsmon upssched
lib_LTLIBRARIES = libupsclient.la
if WITH_DEV
include_HEADERS = upsclient.h ../include/parseconf.h
endif
if WITH_CGI
cgiexec_PROGRAMS = upsstats.cgi upsimage.cgi upsset.cgi
endif
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.a ../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
upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
upsimagearg.h cgilib.c cgilib.h
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libparseconf.la
if WITH_SSL
libupsclient_la_LIBADD += $(LIBSSL_LDFLAGS)
endif
libupsclient_la_LDFLAGS = -version-info 1:0:0

912
clients/Makefile.in Normal file
View file

@ -0,0 +1,912 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# Network UPS Tools: clients
VPATH = @srcdir@
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@
@WITH_SSL_TRUE@am__append_1 = $(LIBSSL_LDFLAGS)
@WITH_SSL_TRUE@am__append_2 = $(LIBSSL_CFLAGS)
@WITH_CGI_TRUE@am__append_3 = $(LIBGD_CFLAGS)
bin_PROGRAMS = upsc$(EXEEXT) upslog$(EXEEXT) upsrw$(EXEEXT) \
upscmd$(EXEEXT)
sbin_PROGRAMS = upsmon$(EXEEXT) upssched$(EXEEXT)
@WITH_CGI_TRUE@cgiexec_PROGRAMS = upsstats.cgi$(EXEEXT) \
@WITH_CGI_TRUE@ upsimage.cgi$(EXEEXT) upsset.cgi$(EXEEXT)
@WITH_SSL_TRUE@am__append_4 = $(LIBSSL_LDFLAGS)
subdir = clients
DIST_COMMON = $(am__include_HEADERS_DIST) $(dist_bin_SCRIPTS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
@WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libupsclient_la_DEPENDENCIES = ../common/libparseconf.la \
$(am__DEPENDENCIES_2)
am_libupsclient_la_OBJECTS = upsclient.lo
libupsclient_la_OBJECTS = $(am_libupsclient_la_OBJECTS)
libupsclient_la_LINK = $(LIBTOOL) --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.a 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.a 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.a 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.a 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.a 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.a libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_upssched_OBJECTS = upssched.$(OBJEXT)
upssched_OBJECTS = $(am_upssched_OBJECTS)
upssched_DEPENDENCIES = ../common/libcommon.a \
../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.a 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.a libupsclient.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
SCRIPTS = $(dist_bin_SCRIPTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
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 = $(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__include_HEADERS_DIST = upsclient.h ../include/parseconf.h
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
# by default, link programs in this directory with libcommon.a
LDADD = ../common/libcommon.a libupsclient.la $(NETLIBS) \
$(am__append_1)
# Avoid per-target CFLAGS, because this will prevent re-use of object
# files. In any case, CFLAGS are only -I options, so there is no harm,
# but only add them if we really use the target.
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_2) $(am__append_3)
dist_bin_SCRIPTS = upssched-cmd
lib_LTLIBRARIES = libupsclient.la
@WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.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.a ../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
upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
upsimagearg.h cgilib.c cgilib.h
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libparseconf.la $(am__append_4)
libupsclient_la_LDFLAGS = -version-info 1:0:0
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(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 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);; \
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):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@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 " $(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)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES)
$(libupsclient_la_LINK) -rpath $(libdir) $(libupsclient_la_OBJECTS) $(libupsclient_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
install-cgiexecPROGRAMS: $(cgiexec_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(cgiexecdir)" || $(MKDIR_P) "$(DESTDIR)$(cgiexecdir)"
@list='$(cgiexec_PROGRAMS)'; test -n "$(cgiexecdir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cgiexecdir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cgiexecdir)$$dir" || exit $$?; \
} \
; done
uninstall-cgiexecPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(cgiexec_PROGRAMS)'; test -n "$(cgiexecdir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(cgiexecdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(cgiexecdir)" && rm -f $$files
clean-cgiexecPROGRAMS:
@list='$(cgiexec_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
} \
; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
upsc$(EXEEXT): $(upsc_OBJECTS) $(upsc_DEPENDENCIES)
@rm -f upsc$(EXEEXT)
$(LINK) $(upsc_OBJECTS) $(upsc_LDADD) $(LIBS)
upscmd$(EXEEXT): $(upscmd_OBJECTS) $(upscmd_DEPENDENCIES)
@rm -f upscmd$(EXEEXT)
$(LINK) $(upscmd_OBJECTS) $(upscmd_LDADD) $(LIBS)
upsimage.cgi$(EXEEXT): $(upsimage_cgi_OBJECTS) $(upsimage_cgi_DEPENDENCIES)
@rm -f upsimage.cgi$(EXEEXT)
$(LINK) $(upsimage_cgi_OBJECTS) $(upsimage_cgi_LDADD) $(LIBS)
upslog$(EXEEXT): $(upslog_OBJECTS) $(upslog_DEPENDENCIES)
@rm -f upslog$(EXEEXT)
$(LINK) $(upslog_OBJECTS) $(upslog_LDADD) $(LIBS)
upsmon$(EXEEXT): $(upsmon_OBJECTS) $(upsmon_DEPENDENCIES)
@rm -f upsmon$(EXEEXT)
$(LINK) $(upsmon_OBJECTS) $(upsmon_LDADD) $(LIBS)
upsrw$(EXEEXT): $(upsrw_OBJECTS) $(upsrw_DEPENDENCIES)
@rm -f upsrw$(EXEEXT)
$(LINK) $(upsrw_OBJECTS) $(upsrw_LDADD) $(LIBS)
upssched$(EXEEXT): $(upssched_OBJECTS) $(upssched_DEPENDENCIES)
@rm -f upssched$(EXEEXT)
$(LINK) $(upssched_OBJECTS) $(upssched_LDADD) $(LIBS)
upsset.cgi$(EXEEXT): $(upsset_cgi_OBJECTS) $(upsset_cgi_DEPENDENCIES)
@rm -f upsset.cgi$(EXEEXT)
$(LINK) $(upsset_cgi_OBJECTS) $(upsset_cgi_LDADD) $(LIBS)
upsstats.cgi$(EXEEXT): $(upsstats_cgi_OBJECTS) $(upsstats_cgi_DEPENDENCIES)
@rm -f upsstats.cgi$(EXEEXT)
$(LINK) $(upsstats_cgi_OBJECTS) $(upsstats_cgi_LDADD) $(LIBS)
install-dist_binSCRIPTS: $(dist_bin_SCRIPTS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n' \
-e 'h;s|.*|.|' \
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
if (++n[d] == $(am__install_max)) { \
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
else { print "f", d "/" $$4, $$1 } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-dist_binSCRIPTS:
@$(NORMAL_UNINSTALL)
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 's,.*/,,;$(transform)'`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgilib.Po@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@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(includedir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(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 $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(HEADERS)
install-binPROGRAMS: install-libLTLIBRARIES
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
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:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-cgiexecPROGRAMS clean-generic \
clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS install-cgiexecPROGRAMS \
install-dist_binSCRIPTS install-libLTLIBRARIES \
install-sbinPROGRAMS
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 -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-cgiexecPROGRAMS \
uninstall-dist_binSCRIPTS uninstall-includeHEADERS \
uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-cgiexecPROGRAMS clean-generic clean-libLTLIBRARIES \
clean-libtool clean-sbinPROGRAMS ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-binPROGRAMS install-cgiexecPROGRAMS \
install-data install-data-am install-dist_binSCRIPTS \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-includeHEADERS \
install-info install-info-am install-libLTLIBRARIES \
install-man install-pdf install-pdf-am install-ps \
install-ps-am install-sbinPROGRAMS 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 uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-cgiexecPROGRAMS uninstall-dist_binSCRIPTS \
uninstall-includeHEADERS uninstall-libLTLIBRARIES \
uninstall-sbinPROGRAMS
# 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:

202
clients/cgilib.c Normal file
View file

@ -0,0 +1,202 @@
/* cgilib - common routines for CGI programs
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
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 <ctype.h>
#include "common.h"
#include "cgilib.h"
#include "parseconf.h"
static char *unescape(char *buf)
{
size_t i, buflen;
char ch, *newbuf, hex[8];
buflen = strlen(buf) + 2;
newbuf = xmalloc(buflen);
*newbuf = '\0';
fflush(stdout);
for (i = 0; i < buflen - 1; i++) {
ch = buf[i];
if (ch == '+')
ch = ' ';
if (ch == '%') {
if (i + 2 > buflen)
fatalx(EXIT_FAILURE, "string too short for escaped char");
hex[0] = buf[++i];
hex[1] = buf[++i];
hex[2] = '\0';
if (!isxdigit((unsigned char) hex[0])
|| !isxdigit((unsigned char) hex[0]))
fatalx(EXIT_FAILURE, "bad escape char");
ch = strtol(hex, NULL, 16);
if ((ch == 10) || (ch == 13))
ch = ' ';
}
snprintfcat(newbuf, buflen, "%c", ch);
}
return newbuf;
}
void extractcgiargs(void)
{
char *query, *ptr, *eq, *varname, *value, *amp;
char *cleanval, *cleanvar;
query = getenv("QUERY_STRING");
if (query == NULL)
return; /* not run as a cgi script! */
if (strlen(query) == 0)
return; /* no query string to parse! */
/* varname=value&varname=value&varname=value ... */
ptr = query;
while (ptr) {
varname = ptr;
eq = strchr(varname, '=');
if (!eq) {
ptr = strchr(varname, '&');
if (ptr)
*ptr++ = '\0';
cleanvar = unescape(varname);
parsearg(cleanvar, "");
free(cleanvar);
continue;
}
*eq = '\0';
value = eq + 1;
amp = strchr(value, '&');
if (amp) {
ptr = amp + 1;
*amp = '\0';
}
else
ptr = NULL;
cleanvar = unescape(varname);
cleanval = unescape(value);
parsearg(cleanvar, cleanval);
free(cleanvar);
free(cleanval);
}
}
void extractpostargs(void)
{
char buf[SMALLBUF], *ptr, *cleanval;
int ch;
ch = fgetc(stdin);
buf[0] = '\0';
while (ch != EOF) {
if (ch == '&') {
ptr = strchr(buf, '=');
if (!ptr)
parsearg(buf, "");
else {
*ptr++ = '\0';
cleanval = unescape(ptr);
parsearg(buf, cleanval);
free(cleanval);
}
buf[0] = '\0';
}
else
snprintfcat(buf, sizeof(buf), "%c", ch);
ch = fgetc(stdin);
}
if (strlen(buf) != 0) {
ptr = strchr(buf, '=');
if (!ptr)
parsearg(buf, "");
else {
*ptr++ = '\0';
cleanval = unescape(ptr);
parsearg(buf, cleanval);
free(cleanval);
}
}
}
/* called for fatal errors in parseconf like malloc failures */
static void cgilib_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg);
}
int checkhost(const char *host, char **desc)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
if (!host)
return 0; /* deny null hostnames */
snprintf(fn, sizeof(fn), "%s/hosts.conf", confpath());
pconf_init(&ctx, cgilib_err);
if (!pconf_file_begin(&ctx, fn)) {
pconf_finish(&ctx);
fprintf(stderr, "%s\n", ctx.errmsg);
return 0; /* failed: deny access */
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
fprintf(stderr, "Error: %s:%d: %s\n",
fn, ctx.linenum, ctx.errmsg);
continue;
}
/* MONITOR <host> <description> */
if (ctx.numargs < 3)
continue;
if (strcmp(ctx.arglist[0], "MONITOR") != 0)
continue;
if (!strcmp(ctx.arglist[1], host)) {
if (desc)
*desc = xstrdup(ctx.arglist[2]);
pconf_finish(&ctx);
return 1; /* found: allow access */
}
}
pconf_finish(&ctx);
return 0; /* not found: access denied */
}

31
clients/cgilib.h Normal file
View file

@ -0,0 +1,31 @@
/* cgilib.h - headers for cgilib.c
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
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
*/
/* other programs that link to this should provide parsearg() ... */
void parsearg(char *var, char *value);
/* actually extract the values from QUERY_STRING */
void extractcgiargs(void);
/* like extractcgiargs, but this one is for POSTed values */
void extractpostargs(void);
/* see if a host is allowed per the hosts.conf */
int checkhost(const char *host, char **desc);

37
clients/status.h Normal file
View file

@ -0,0 +1,37 @@
/* status.h - translation of status abbreviations to descriptions
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
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
*/
struct {
char *name;
char *desc;
int severity;
} stattab[] =
{
{ "OFF", "OFF", 1 },
{ "OL", "ONLINE", 0 },
{ "OB", "ON BATTERY", 2 },
{ "LB", "LOW BATTERY", 2 },
{ "RB", "REPLACE BATTERY", 2 },
{ "OVER", "OVERLOAD", 2 },
{ "TRIM", "VOLTAGE TRIM", 1 },
{ "BOOST", "VOLTAGE BOOST", 1 },
{ "CAL", "CALIBRATION", 1 },
{ "BYPASS", "BYPASS", 2 },
{ NULL, NULL, 0 }
};

229
clients/upsc.c Normal file
View file

@ -0,0 +1,229 @@
/* upsc - simple "client" to test communications
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "upsclient.h"
static char *upsname = NULL, *hostname = NULL;
static UPSCONN_t *ups = NULL;
static void usage(const char *prog)
{
printf("Network UPS Tools upsc %s\n\n", UPS_VERSION);
printf("usage: %s -l | -L [<hostname>[:port]]\n", prog);
printf(" %s <ups> [<variable>]\n", prog);
printf("\nDemo program to display UPS variables.\n\n");
printf("First form (lists UPSes):\n");
printf(" -l - lists each UPS on <hostname>, one per line.\n");
printf(" -L - lists each UPS followed by its description (from ups.conf).\n");
printf(" Default hostname: localhost\n");
printf("\nSecond form (lists variables and values):\n");
printf(" <ups> - upsd server, <upsname>[@<hostname>[:<port>]] form\n");
printf(" <variable> - optional, display this variable only.\n");
printf(" Default: list all variables for <host>\n");
}
static void printvar(const char *var)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
/* old-style variable name? */
if (!strchr(var, '.')) {
fatalx(EXIT_FAILURE, "Error: old-style variable names are not supported");
}
query[0] = "VAR";
query[1] = upsname;
query[2] = var;
numq = 3;
ret = upscli_get(ups, numq, query, &numa, &answer);
if (ret < 0) {
/* new var and old upsd? try to explain the situation */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Error: variable unknown (old upsd detected)");
}
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
if (numa < numq) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least %d)", numa, numq);
}
printf("%s\n", answer[3]);
}
static void list_vars(void)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
query[0] = "VAR";
query[1] = upsname;
numq = 2;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
/* check for an old upsd */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query");
}
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) {
/* VAR <upsname> <varname> <val> */
if (numa < 4) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
}
printf("%s: %s\n", answer[2], answer[3]);
}
}
static void list_upses(int verbose)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
query[0] = "UPS";
numq = 1;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
/* check for an old upsd */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query");
}
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) {
/* UPS <upsname> <description> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
}
if(verbose) {
printf("%s: %s\n", answer[1], answer[2]);
} else {
printf("%s\n", answer[1]);
}
}
}
static void clean_exit(void)
{
if (ups) {
upscli_disconnect(ups);
}
free(upsname);
free(hostname);
free(ups);
}
int main(int argc, char **argv)
{
int i, port;
int varlist = 0, verbose = 0;
const char *prog = xbasename(argv[0]);
while ((i = getopt(argc, argv, "+hlLV")) != -1) {
switch (i)
{
case 'L':
verbose = 1;
case 'l':
varlist = 1;
break;
case 'V':
fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION);
case 'h':
default:
usage(prog);
exit(EXIT_SUCCESS);
}
}
argc -= optind;
argv += optind;
/* be a good little client that cleans up after itself */
atexit(clean_exit);
if (varlist) {
if (upscli_splitaddr(argv[0] ? argv[0] : "localhost", &hostname, &port) != 0) {
fatalx(EXIT_FAILURE, "Error: invalid hostname.\nRequired format: [hostname[:port]]");
}
} else {
if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) {
fatalx(EXIT_FAILURE, "Error: invalid UPS definition.\nRequired format: upsname[@hostname[:port]]");
}
}
ups = xmalloc(sizeof(*ups));
if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) {
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
if (varlist) {
list_upses(verbose);
exit(EXIT_SUCCESS);
}
if (argc > 1) {
printvar(argv[1]);
} else {
list_vars();
}
exit(EXIT_SUCCESS);
}

1108
clients/upsclient.c Normal file

File diff suppressed because it is too large Load diff

166
clients/upsclient.h Normal file
View file

@ -0,0 +1,166 @@
/* upsclient.h - definitions for upsclient functions
Copyright (C) 2002 Russell Kroll <rkroll@exploits.org>
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 UPSCLIENT_H_SEEN
#define UPSCLIENT_H_SEEN
#ifdef HAVE_SSL
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define UPSCLI_ERRBUF_LEN 256
#define UPSCLI_NETBUF_LEN 512 /* network i/o buffer */
#include "parseconf.h"
typedef struct {
char *host;
int port;
int fd;
int flags;
int upserror;
int syserrno;
int upsclient_magic;
PCONF_CTX_t pc_ctx;
char errbuf[UPSCLI_ERRBUF_LEN];
#ifdef HAVE_SSL
SSL_CTX *ssl_ctx;
SSL *ssl;
#else
void *ssl_ctx;
void *ssl;
#endif
char readbuf[64];
size_t readlen;
size_t readidx;
} UPSCONN_t;
const char *upscli_strerror(UPSCONN_t *ups);
int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags);
/* --- 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_list_start(UPSCONN_t *ups, unsigned int numq, const char **query);
int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer);
int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen);
int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen);
int upscli_splitname(const char *buf, char **upsname, char **hostname,
int *port);
int upscli_splitaddr(const char *buf, char **hostname, int *port);
int upscli_sslcert(UPSCONN_t *ups, const char *file, const char *path, int verify);
int upscli_disconnect(UPSCONN_t *ups);
/* these functions return elements from UPSCONN_t to avoid direct references */
int upscli_fd(UPSCONN_t *ups);
int upscli_upserror(UPSCONN_t *ups);
/* returns 1 if SSL mode is active for this connection */
int upscli_ssl(UPSCONN_t *ups);
/* upsclient error list */
#define UPSCLI_ERR_UNKNOWN 0 /* Unknown error */
#define UPSCLI_ERR_VARNOTSUPP 1 /* Variable not supported by UPS */
#define UPSCLI_ERR_NOSUCHHOST 2 /* No such host */
#define UPSCLI_ERR_INVRESP 3 /* Invalid response from server */
#define UPSCLI_ERR_UNKNOWNUPS 4 /* Unknown UPS */
#define UPSCLI_ERR_INVLISTTYPE 5 /* Invalid list type */
#define UPSCLI_ERR_ACCESSDENIED 6 /* Access denied */
#define UPSCLI_ERR_PWDREQUIRED 7 /* Password required */
#define UPSCLI_ERR_PWDINCORRECT 8 /* Password incorrect */
#define UPSCLI_ERR_MISSINGARG 9 /* Missing argument */
#define UPSCLI_ERR_DATASTALE 10 /* Data stale */
#define UPSCLI_ERR_VARUNKNOWN 11 /* Variable unknown */
#define UPSCLI_ERR_LOGINTWICE 12 /* Already logged in */
#define UPSCLI_ERR_PWDSETTWICE 13 /* Already set password */
#define UPSCLI_ERR_UNKNOWNTYPE 14 /* Unknown variable type */
#define UPSCLI_ERR_UNKNOWNVAR 15 /* Unknown variable */
#define UPSCLI_ERR_VARREADONLY 16 /* Read-only variable */
#define UPSCLI_ERR_TOOLONG 17 /* New value is too long */
#define UPSCLI_ERR_INVALIDVALUE 18 /* Invalid value for variable */
#define UPSCLI_ERR_SETFAILED 19 /* Set command failed */
#define UPSCLI_ERR_UNKINSTCMD 20 /* Unknown instant command */
#define UPSCLI_ERR_CMDFAILED 21 /* Instant command failed */
#define UPSCLI_ERR_CMDNOTSUPP 22 /* Instant command not supported */
#define UPSCLI_ERR_INVUSERNAME 23 /* Invalid username */
#define UPSCLI_ERR_USERSETTWICE 24 /* Already set username */
#define UPSCLI_ERR_UNKCOMMAND 25 /* Unknown command */
#define UPSCLI_ERR_INVALIDARG 26 /* Invalid argument */
#define UPSCLI_ERR_SENDFAILURE 27 /* Send failure: %s */
#define UPSCLI_ERR_RECVFAILURE 28 /* Receive failure: %s */
#define UPSCLI_ERR_SOCKFAILURE 29 /* socket failure: %s */
#define UPSCLI_ERR_BINDFAILURE 30 /* bind failure: %s */
#define UPSCLI_ERR_CONNFAILURE 31 /* Connection failure: %s */
#define UPSCLI_ERR_WRITE 32 /* Write error: %s */
#define UPSCLI_ERR_READ 33 /* Read error: %s */
#define UPSCLI_ERR_INVPASSWORD 34 /* Invalid password */
#define UPSCLI_ERR_USERREQUIRED 35 /* Username required */
#define UPSCLI_ERR_SSLFAIL 36 /* SSL is not available */
#define UPSCLI_ERR_SSLERR 37 /* SSL error: %s */
#define UPSCLI_ERR_SRVDISC 38 /* Server disconnected */
#define UPSCLI_ERR_DRVNOTCONN 39 /* Driver not connected */
#define UPSCLI_ERR_NOMEM 40 /* Memory allocation failure */
#define UPSCLI_ERR_PARSE 41 /* Parse error: %s */
#define UPSCLI_ERR_PROTOCOL 42 /* Protocol error */
#define UPSCLI_ERR_MAX 42 /* stop here */
/* list types for use with upscli_getlist */
#define UPSCLI_LIST_VARS 1 /* all variables */
#define UPSCLI_LIST_RW 2 /* just read/write variables */
#define UPSCLI_LIST_CMDS 3 /* instant commands */
/* flags for use with upscli_connect */
#define UPSCLI_CONN_TRYSSL 0x0001 /* try SSL, OK if not supported */
#define UPSCLI_CONN_REQSSL 0x0002 /* try SSL, fail if not supported */
#ifdef HAVE_IPV6
#define UPSCLI_CONN_INET 0x0004 /* IPv4 only */
#define UPSCLI_CONN_INET6 0x0008 /* IPv6 only */
#endif
#ifdef __cplusplus
}
#endif
#endif /* UPSCLIENT_H_SEEN */

311
clients/upscmd.c Normal file
View file

@ -0,0 +1,311 @@
/* upscmd - simple "client" to test instant commands via upsd
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include <pwd.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "upsclient.h"
static char *upsname = NULL, *hostname = NULL;
static UPSCONN_t *ups = NULL;
struct list_t {
char *name;
struct list_t *next;
};
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("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("\n");
printf(" <ups> UPS identifier - <upsname>[@<hostname>[:<port>]]\n");
printf(" <command> Valid instant command - test.panel.start, etc.\n");
printf(" [<value>] Additional data for command - number of seconds, etc.\n");
}
static void print_cmd(char *cmdname)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
query[0] = "CMDDESC";
query[1] = upsname;
query[2] = cmdname;
numq = 3;
ret = upscli_get(ups, numq, query, &numa, &answer);
if ((ret < 0) || (numa < numq)) {
printf("%s\n", cmdname);
return;
}
/* CMDDESC <upsname> <cmdname> <desc> */
printf("%s - %s\n", cmdname, answer[3]);
}
static void listcmds(void)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
struct list_t *lhead = NULL, *llast = NULL, *ltmp, *lnext;
query[0] = "CMD";
query[1] = upsname;
numq = 2;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
/* old upsd = no way to continue */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query");
}
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) {
/* CMD <upsname> <cmdname> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
}
/* we must first read the entire list of commands,
before we can start reading the descriptions */
ltmp = xcalloc(1, sizeof(*ltmp));
ltmp->name = xstrdup(answer[2]);
if (llast) {
llast->next = ltmp;
} else {
lhead = ltmp;
}
llast = ltmp;
}
/* walk the list and try to get descriptions, freeing as we go */
printf("Instant commands supported on UPS [%s]:\n\n", upsname);
for (ltmp = lhead; ltmp; ltmp = lnext) {
lnext = ltmp->next;
print_cmd(ltmp->name);
free(ltmp->name);
free(ltmp);
}
}
static void do_cmd(char **argv, const int argc)
{
char buf[SMALLBUF];
if (argc > 1) {
snprintf(buf, sizeof(buf), "INSTCMD %s %s %s\n", upsname, argv[0], argv[1]);
} else {
snprintf(buf, sizeof(buf), "INSTCMD %s %s\n", upsname, argv[0]);
}
if (upscli_sendline(ups, buf, strlen(buf)) < 0) {
fatalx(EXIT_FAILURE, "Can't send instant command: %s", upscli_strerror(ups));
}
if (upscli_readline(ups, buf, sizeof(buf)) < 0) {
fatalx(EXIT_FAILURE, "Instant command failed: %s", upscli_strerror(ups));
}
}
static void clean_exit(void)
{
if (ups) {
upscli_disconnect(ups);
}
free(upsname);
free(hostname);
free(ups);
}
int main(int argc, char **argv)
{
int i, ret, port;
int have_un = 0, have_pw = 0, cmdlist = 0;
char buf[SMALLBUF], username[SMALLBUF], password[SMALLBUF];
const char *prog = xbasename(argv[0]);
while ((i = getopt(argc, argv, "+lhu:p:V")) != -1) {
switch (i)
{
case 'l':
cmdlist = 1;
break;
case 'u':
snprintf(username, sizeof(username), "%s", optarg);
have_un = 1;
break;
case 'p':
snprintf(password, sizeof(password), "%s", optarg);
have_pw = 1;
break;
case 'V':
fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION);
case 'h':
default:
usage(prog);
exit(EXIT_SUCCESS);
}
}
argc -= optind;
argv += optind;
if (argc < 1) {
usage(prog);
exit(EXIT_SUCCESS);
}
/* be a good little client that cleans up after itself */
atexit(clean_exit);
if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) {
fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]");
}
ups = xcalloc(1, sizeof(*ups));
if (upscli_connect(ups, hostname, port, 0) < 0) {
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
}
if (cmdlist) {
listcmds();
exit(EXIT_SUCCESS);
}
if (argc < 2) {
usage(prog);
exit(EXIT_SUCCESS);
}
/* also fallback for old command names */
if (!strchr(argv[1], '.')) {
fatalx(EXIT_FAILURE, "Error: old command names are not supported");
}
if (!have_un) {
struct passwd *pw;
memset(username, '\0', sizeof(username));
pw = getpwuid(getuid());
if (pw) {
printf("Username (%s): ", pw->pw_name);
} else {
printf("Username: ");
}
if (!fgets(username, sizeof(username), stdin)) {
fatalx(EXIT_FAILURE, "Error reading from stdin!");
}
/* deal with that pesky newline */
if (strlen(username) > 1) {
username[strlen(username) - 1] = '\0';
} else {
if (!pw) {
fatalx(EXIT_FAILURE, "No username available - even tried getpwuid");
}
snprintf(username, sizeof(username), "%s", pw->pw_name);
}
}
/* getpass leaks slightly - use -p when testing in valgrind */
if (!have_pw) {
/* using getpass or getpass_r might not be a
good idea here (marked obsolete in POSIX) */
char *pwtmp = GETPASS("Password: ");
if (!pwtmp) {
fatalx(EXIT_FAILURE, "getpass failed: %s", strerror(errno));
}
snprintf(password, sizeof(password), "%s", pwtmp);
}
snprintf(buf, sizeof(buf), "USERNAME %s\n", username);
if (upscli_sendline(ups, buf, strlen(buf)) < 0) {
fatalx(EXIT_FAILURE, "Can't set username: %s", upscli_strerror(ups));
}
ret = upscli_readline(ups, buf, sizeof(buf));
if (ret < 0) {
if (upscli_upserror(ups) != UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Set username failed: %s", upscli_strerror(ups));
}
fatalx(EXIT_FAILURE,
"Set username failed due to an unknown command.\n"
"You probably need to upgrade upsd.");
}
snprintf(buf, sizeof(buf), "PASSWORD %s\n", password);
if (upscli_sendline(ups, buf, strlen(buf)) < 0) {
fatalx(EXIT_FAILURE, "Can't set password: %s", upscli_strerror(ups));
}
if (upscli_readline(ups, buf, sizeof(buf)) < 0) {
fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups));
}
do_cmd(&argv[1], argc - 1);
exit(EXIT_SUCCESS);
}

731
clients/upsimage.c Normal file
View file

@ -0,0 +1,731 @@
/* upsimage - cgi program to create graphical ups information reports
Status:
20020814 - Simon Rozman
- redesigned the meters
20020823 - Simon Rozman
- added support for width, height and scale_height parameters
- added support for outvolt
- noimage now writes out a clue, why upsimage failed
20020902 - Simon Rozman
- background now transparent by default
- added support for colorization parameters
- removed linear antialiasing of the scale, until I come up with a better algorithm
20020913 - Simon Rozman
- added width, height and scale_height to imgarg table
20020928 - Simon Rozman
- added imgvar table to hold description, how to draw each UPS variable supported
- added support for ACFREQ, OUT_FREQ and UPSTEMP
Copyrights:
(C) 1998 Russell Kroll <rkroll@exploits.org>
(C) 2002 Simon Rozman <simon@rozman.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsclient.h"
#include "cgilib.h"
#include <stdlib.h>
#include <gd.h>
#include <gdfontmb.h>
#include "upsimagearg.h"
#define MAX_CGI_STRLEN 64
static char *monhost = NULL, *cmd = NULL;
static int port;
static char *upsname, *hostname;
static UPSCONN_t ups;
#define RED(x) ((x >> 16) & 0xff)
#define GREEN(x) ((x >> 8) & 0xff)
#define BLUE(x) (x & 0xff)
void parsearg(char *var, char *value)
{
int i, v;
/* avoid bogus junk from evil people */
if ((strlen(var) > MAX_CGI_STRLEN) || (strlen(value) > MAX_CGI_STRLEN))
return;
if (!strcmp(var, "host")) {
free(monhost);
monhost = xstrdup(value);
return;
}
if (!strcmp(var, "display")) {
free(cmd);
cmd = xstrdup(value);
return;
}
/* see if this is one of the shared (upsimagearg.h) variables */
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);
else
v = 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;
return;
}
}
}
/* return the value from the URL or the default if it wasn't set */
static int get_imgarg(const char *name)
{
int i;
for (i = 0; imgarg[i].name != NULL; i++)
if (!strcmp(imgarg[i].name, name))
return imgarg[i].val;
return -1;
}
/* write the HTML header then have gd dump the image */
static void drawimage(gdImagePtr im)
{
printf("Pragma: no-cache\n");
printf("Content-type: image/png\n\n");
gdImagePng(im, stdout);
gdImageDestroy(im);
upscli_disconnect(&ups);
exit(EXIT_SUCCESS);
}
/* helper function to allocate color in the image */
static int color_alloc(gdImagePtr im, int rgb)
{
return gdImageColorAllocate(im, RED(rgb), GREEN(rgb), BLUE(rgb));
}
/* draws the scale behind the bar indicator */
static void drawscale(
gdImagePtr im, /* image where we would like to draw scale */
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 */
{
int col1, col2, back_color, scale_num_color, ok_zone_maj_color,
ok_zone_min_color, neutral_zone_maj_color,
neutral_zone_min_color, warn_zone_maj_color,
warn_zone_min_color;
char lbltxt[SMALLBUF];
int y, level, range;
int width, height, scale_height;
back_color = color_alloc(im, get_imgarg("back_col"));
scale_num_color = color_alloc(im, get_imgarg("scale_num_col"));
ok_zone_maj_color = color_alloc(im, get_imgarg("ok_zone_maj_col"));
ok_zone_min_color = color_alloc(im, get_imgarg("ok_zone_min_col"));
neutral_zone_maj_color = color_alloc(im, get_imgarg("neutral_zone_maj_col"));
neutral_zone_min_color = color_alloc(im, get_imgarg("neutral_zone_min_col"));
warn_zone_maj_color = color_alloc(im, get_imgarg("warn_zone_maj_col"));
warn_zone_min_color = color_alloc(im, get_imgarg("warn_zone_min_col"));
width = get_imgarg("width");
height = get_imgarg("height");
scale_height = get_imgarg("scale_height");
/* start out with a background color and make it transparent */
gdImageFilledRectangle(im, 0, 0, width, height, back_color);
gdImageColorTransparent(im, back_color);
range = lvlhi - lvllo;
/* draw scale to correspond with the values */
for (level = lvlhi; level >= lvllo; level -= step) {
/* select dash RGB color according to the level */
if (((redlo1 <= level) && (level <=redhi1)) ||
((redlo2 <= level) && (level <=redhi2))) {
col1 = warn_zone_maj_color;
col2 = warn_zone_min_color;
} else if ((grnlo <= level) && (level <= grnhi)) {
col1 = ok_zone_maj_color;
col2 = ok_zone_min_color;
} else {
col1 = neutral_zone_maj_color;
col2 = neutral_zone_min_color;
}
/* calculate integer value for y */
y = scale_height * (lvlhi - level) / range;
/* draw major, semimajor or minor dash accordingly */
if (level % step10 == 0) {
gdImageLine(im, 0, y, width, y, col1);
} else {
if (level % step5 == 0)
gdImageLine(im, 5, y, width - 5, y, col2);
else
gdImageLine(im, 10, y, width - 10, y, col2);
}
}
/* put the values on the scale */
for (level = lvlhi; level >= lvllo; level -= step) {
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);
}
}
}
/* 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 */
)
{
gdImagePtr im;
int bar_color, summary_color;
char text[SMALLBUF];
int bar_y;
int width, height, scale_height;
/* get the dimension parameters */
width = get_imgarg("width");
height = get_imgarg("height");
scale_height = get_imgarg("scale_height");
/* create the image */
im = gdImageCreate(width, height);
/* draw the scale */
drawscale(im, lvllo, lvlhi, step, step5, step10, redlo1, redhi1,
redlo2, redhi2, grnlo, grnhi);
/* allocate colors for the bar and summary text */
bar_color = color_alloc(im, get_imgarg("bar_col"));
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;
/* sanity checks: */
/* 1: if value is above maximum, then bar_y goes negative */
if (bar_y < 0)
bar_y = 0;
/* 2: if value is below minimum, bar_y goes off the scale */
if (bar_y > scale_height)
bar_y = scale_height;
/* draw it */
gdImageFilledRectangle(im, 25, bar_y, width - 25, scale_height,
bar_color);
/* stick the text version of the value at the bottom center */
snprintf(text, sizeof(text), format, value);
gdImageString(im, gdFontMediumBold,
(width - strlen(text)*gdFontMediumBold->w)/2,
height - gdFontMediumBold->h,
(unsigned char *) text, summary_color);
drawimage(im);
/* NOTREACHED */
}
/* draws the error image */
static void noimage(const char *fmt, ...)
{
gdImagePtr im;
int back_color, summary_color;
int width, height;
char msg[SMALLBUF];
va_list ap;
va_start(ap, fmt);
vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
width = get_imgarg("width");
height = get_imgarg("height");
im = gdImageCreate(width, height);
back_color = color_alloc(im, get_imgarg("back_col"));
summary_color = color_alloc(im, get_imgarg("summary_col"));
gdImageFilledRectangle(im, 0, 0, width, height, back_color);
gdImageColorTransparent(im, back_color);
if (width > height)
gdImageString(im, gdFontMediumBold,
(width - 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,
(unsigned char *) msg, summary_color);
drawimage(im);
/* NOTREACHED */
}
/* draws bar indicator when minimum, nominal or maximum values for the given
UPS variable can be determined.
deviation < 0 means that values below nom should be grey instead of
green */
static void drawgeneralbar(double var, int min, int nom, int max,
int deviation, const char *format)
{
int hi, lo, step1, step5, step10, graybelownom=0;
if(deviation < 0) {
deviation=-deviation;
graybelownom=1;
}
if ((nom == -1) && ((min == -1) || (max == -1)))
noimage("Can't determine range");
/* if min, max and nom are mixed up, arrange them appropriately */
if (nom != -1) {
if (min == -1)
min = nom - 3*deviation;
if (max == -1)
max = nom + 3*deviation;
} else {
/* if nominal value isn't available, assume, it's the
average between min and max */
nom = (min + max) / 2;
}
/* draw scale in the background */
if ((max - min) <= 50) {
/* the scale is sparse enough to draw finer scale */
step1 = 1;
step5 = 5;
step10 = 10;
} else if((max - min) <= 100) {
step1 = 2;
step5 = 10;
step10 = 20;
} else {
step1 = 5;
step5 = 20;
step10 = 40;
}
/* round min and max points to get high and low numbers for graph */
lo = ((min - deviation) / step10) * step10;
hi = ((max + deviation + step10/2) / step10) * step10;
if(!graybelownom) {
drawbar(lo, hi, step1, step5, step10, max, hi, lo, min,
nom - deviation, nom + deviation, var, format);
}
else {
drawbar(lo, hi, step1, step5, step10, 0, min, max, hi,
nom, max, var, format);
}
/* NOTREACHED */
}
/* 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)
{
/* hack: deal with hardware that doesn't have known transfer points */
if (min == -1) {
if(var < 200) {
min = 90;
}
else if(var < 300) {
min = 200;
}
else {
min = 340;
}
}
/* somewhere between 220 and 230 V, to keep everybody satisfied */
if (nom == -1) {
if(var < 200) {
nom = 110;
}
else if(var < 300) {
nom = 225;
}
else {
nom = 400;
}
}
/* symmetrical around nom */
if (max == -1)
max = nom+(nom-min);
/* Acceptable range of voltage is 85%-110% of nominal voltage
* in EU at least. Be conservative and say +-10% */
deviation = nom*0.1;
drawgeneralbar(var, min, nom, max, deviation, format);
/* NOTREACHED */
}
/* draws battery.percent bar style indicator */
static void draw_battpct(double var, int min, int nom, int max,
int deviation, const char *format)
{
if (min < 0) {
min = 50;
}
drawbar(0, 100, 2, 10, 20, 0, min, -1, -1, 80, 100, var, format);
}
/* draws battery.voltage bar style indicator */
static void draw_battvolt(double var, int min, int nom, int max,
int deviation, const char *format)
{
if(nom == -1) {
/* Use a fixed set of reasonable nominal voltages, seems to
* be the only way to get reasonable behaviour during
* discharge */
if(var < 9)
nom = 6;
else if(var < 18)
nom = 12;
else if(var < 30)
nom = 24;
else if(var < 60)
nom = 48;
else if(var < 120)
nom = 96;
else if(var < 230)
nom = 192;
else
nom = 384;
}
if(min == -1) {
min = 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 */
}
if (nom < min || nom > max)
nom = -1;
deviation = -(nom*0.05); /* 5% deviation from nominal voltage */
if(deviation==0) {
deviation = -1;
}
drawgeneralbar(var, min, nom, max, deviation, format);
}
/* draws ups.load bar style indicator */
static void draw_upsload(double var, int min, int nom, int max,
int deviation, const char *format)
{
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)
{
int hi = get_imgarg("tempmax");
int lo = get_imgarg("tempmin");
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)
{
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;
const char *query[4];
char **answer;
query[0] = "VAR";
query[1] = upsname;
query[2] = var;
numq = 3;
ret = upscli_get(&ups, numq, query, &numa, &answer);
if (ret < 0)
return 0;
if (numa < numq)
return 0;
snprintf(buf, buflen, "%s", answer[3]);
return 1;
}
int main(int argc, char **argv)
{
char str[SMALLBUF];
int i, min, nom, max;
double var = 0;
extractcgiargs();
/* no 'host=' or 'display=' given */
if ((!monhost) || (!cmd))
noimage("No host or display");
if (!checkhost(monhost, NULL))
noimage("Access denied");
upsname = hostname = NULL;
if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) {
noimage("Invalid UPS definition (upsname[@hostname[:port]])\n");
exit(EXIT_FAILURE);
}
if (upscli_connect(&ups, hostname, port, 0) < 0) {
noimage("Can't connect to server:\n%s\n",
upscli_strerror(&ups));
exit(EXIT_FAILURE);
}
for (i = 0; imgvar[i].name; i++)
if (!strcmp(cmd, imgvar[i].name)) {
/* sanity check whether we have draw function
registered with this variable */
if (!imgvar[i].drawfunc) {
noimage("Draw function N/A");
exit(EXIT_FAILURE);
}
/* get the variable value */
if (get_var(imgvar[i].name, str, sizeof(str)) == 1) {
var = strtod(str, NULL);
} else {
/* no value, no fun */
snprintf(str, sizeof(str), "%s N/A",
imgvar[i].name);
noimage(str);
exit(EXIT_FAILURE);
}
/* when getting minimum, nominal and maximum values,
we first look if the marginal value is supported
by the UPS driver, if not, we look it up in the
imgarg table under the SAME name */
/* get the minimum value */
if (imgvar[i].minimum) {
if (get_var(imgvar[i].minimum, str,
sizeof(str)) == 1) {
min = atoi(str);
} else {
min = get_imgarg(imgvar[i].minimum);
}
} else {
min = -1;
}
/* get the nominal value */
if (imgvar[i].nominal) {
if (get_var(imgvar[i].nominal, str,
sizeof(str)) == 1) {
nom = atoi(str);
} else {
nom = get_imgarg(imgvar[i].nominal);
}
} else {
nom = -1;
}
/* get the maximum value */
if (imgvar[i].maximum) {
if (get_var(imgvar[i].maximum, str,
sizeof(str)) == 1) {
max = atoi(str);
} else {
max = get_imgarg(imgvar[i].maximum);
}
} else {
max = -1;
}
imgvar[i].drawfunc(var, min, nom, max,
imgvar[i].deviation, imgvar[i].format);
exit(EXIT_SUCCESS);
}
noimage("Unknown display");
exit(EXIT_FAILURE);
}
struct imgvar_t imgvar[] = {
{ "input.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L1-N.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L2-N.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L3-N.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L1-L2.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L2-L3.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "input.L3-L1.voltage", "input.transfer.low", "input.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "battery.charge", "battery.charge.low", NULL, NULL, 0,
"%.1f %%", draw_battpct },
{ "battery.voltage", "battery.voltage.low", "battery.voltage.nominal",
"battery.voltage.high", 0,
"%.1f VDC", draw_battvolt },
/* We use 'high' ASCII for the degrees symbol, since the gdImageString()
* function doesn't understand UTF-8 or HTML escape sequences. :-( */
{ "ups.temperature", "ups.temperature.low", NULL,
"ups.temperature.high", 0,
"%.1f \260C", draw_temperature },
/* Same here. */
{ "ambient.temperature", "ambient.temperature.low", NULL,
"ambient.temperature.high", 0,
"%.1f \260C", draw_temperature },
{ "ambient.humidity", "ambient.humidity.low", NULL,
"ambient.humidity.high", 0,
"%.1f %%", draw_humidity },
{ "input.frequency", NULL, "input.frequency.nominal", NULL, 2,
"%.1f Hz", drawgeneralbar },
{ "ups.load", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L1.power.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L2.power.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L3.power.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L1.realpower.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L2.realpower.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.L3.realpower.percent", NULL, NULL, NULL, 0,
"%.1f %%", draw_upsload },
{ "output.voltage", "input.transfer.low", "output.voltage.nominal",
"input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L1-N.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L2-N.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L3-N.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L1-L2.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L2-L3.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.L3-L1.voltage", "input.transfer.low",
"output.voltage.nominal", "input.transfer.high", 0,
"%.1f VAC", draw_utility },
{ "output.frequency", NULL, "output.frequency.nominal", NULL, 2,
"%.1f Hz", drawgeneralbar },
{ NULL, NULL, NULL, NULL, 0,
NULL, NULL }
};

60
clients/upsimagearg.h Normal file
View file

@ -0,0 +1,60 @@
/* upsimagearg.h - arguments passed between upsstats and upsimage
Copyright (C) 2002 Russell Kroll <rkroll@exploits.org>
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
*/
struct {
char *name;
int val; /* hex digits, ala HTML */
int min; /* minimum reasonable value */
int max; /* maximum reasonable value */
} imgarg[] =
{
{ "width", 100, 50, 200 },
{ "height", 350, 100, 500 },
{ "scale_height", 300, 100, 500 },
{ "back_col", 0x000000, 0x000000, 0xffffff },
{ "scale_num_col", 0xffff00, 0x000000, 0xffffff },
{ "summary_col", 0xffff00, 0x000000, 0xffffff },
{ "ok_zone_maj_col", 0x00ff00, 0x000000, 0xffffff },
{ "ok_zone_min_col", 0x007800, 0x000000, 0xffffff },
{ "neutral_zone_maj_col", 0xffffff, 0x000000, 0xffffff },
{ "neutral_zone_min_col", 0x646464, 0x000000, 0xffffff },
{ "warn_zone_maj_col", 0xff0000, 0x000000, 0xffffff },
{ "warn_zone_min_col", 0x960000, 0x000000, 0xffffff },
{ "bar_col", 0x00ff00, 0x000000, 0xffffff },
{ "tempmin", 0, -100, 150 },
{ "tempmax", 40, -100, 150 },
{ "nom_in_freq", 50, 0, 100 },
{ "nom_out_freq", 50, 0, 100 },
{ NULL, 0, 0, 0 }
};
struct imgvar_t {
char *name; /* name of the UPS variable */
char *minimum; /* name of minimum value UPS variable
or variable in imgarg table */
char *nominal; /* as above, only for nominal value */
char *maximum; /* as above, only for maximum value */
int deviation; /* variable deviation - width of green zone */
char *format; /* format string to generate summary text */
/* pointer to drawing function */
void (*drawfunc)(double, int, int, int, int, const char*);
};
extern struct imgvar_t imgvar[];

532
clients/upslog.c Normal file
View file

@ -0,0 +1,532 @@
/* upslog - log ups values to a file for later collection and analysis
Copyright (C) 1998 Russell Kroll <rkroll@exploits.org>
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
*/
/* Basic theory of operation:
*
* First we go through and parse as much of the status format string as
* possible. We used to do this parsing run every time, but that's a
* waste of CPU since it can't change during the program's run.
*
* This version does the parsing pass once, and creates a linked list of
* pointers to the functions that do the work and the arg they get.
*
* That means the main loop just has to run the linked list and call
* anything it finds in there. Everything happens from there, and we
* don't have to pointlessly reparse the string every time around.
*/
#include "common.h"
#include "upsclient.h"
#include "config.h"
#include "timehead.h"
#include "upslog.h"
static int port, reopen_flag = 0, exit_flag = 0;
static char *upsname, *hostname;
static UPSCONN_t ups;
static FILE *logfile;
static const char *logfn, *monhost;
static sigset_t nut_upslog_sigmask;
static char logbuffer[LARGEBUF], *logformat;
static struct flist_t *fhead = NULL;
#define DEFAULT_LOGFORMAT "%TIME @Y@m@d @H@M@S% %VAR battery.charge% " \
"%VAR input.voltage% %VAR ups.load% [%VAR ups.status%] " \
"%VAR ups.temperature% %VAR input.frequency%"
static void reopen_log(void)
{
if (logfile == stdout) {
upslogx(LOG_INFO, "logging to stdout");
return;
}
fclose(logfile);
logfile = fopen(logfn, "a");
if (logfile == NULL)
fatal_with_errno(EXIT_FAILURE, "could not reopen logfile %s", logfn);
}
static void set_reopen_flag(int sig)
{
reopen_flag = sig;
}
static void set_exit_flag(int sig)
{
exit_flag = sig;
}
/* handlers: reload on HUP, exit on INT/QUIT/TERM */
static void setup_signals(void)
{
struct sigaction sa;
sigemptyset(&nut_upslog_sigmask);
sigaddset(&nut_upslog_sigmask, SIGHUP);
sa.sa_mask = nut_upslog_sigmask;
sa.sa_handler = set_reopen_flag;
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGHUP handler");
sa.sa_handler = set_exit_flag;
if (sigaction(SIGINT, &sa, NULL) < 0)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGINT handler");
if (sigaction(SIGQUIT, &sa, NULL) < 0)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGQUIT handler");
if (sigaction(SIGTERM, &sa, NULL) < 0)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGTERM handler");
}
static void help(const char *prog)
{
printf("UPS status logger.\n");
printf("\nusage: %s [OPTIONS]\n", prog);
printf("\n");
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(" -p <pidbase> - Base name for PID file (defaults to \"upslog\")\n");
printf(" -s <ups> - Monitor UPS <ups> - <upsname>@<host>[:<port>]\n");
printf(" - Example: -s myups@server\n");
printf(" -u <user> - Switch to <user> if started as root\n");
printf("\n");
printf("Some valid format string escapes:\n");
printf("\t%%%% insert a single %%\n");
printf("\t%%TIME format%% insert the time with strftime formatting\n");
printf("\t%%HOST%% insert the local hostname\n");
printf("\t%%UPSHOST%% insert the host of the ups being monitored\n");
printf("\t%%PID%% insert the pid of upslog\n");
printf("\t%%VAR varname%% insert the value of ups variable varname\n\n");
printf("format string defaults to:\n");
printf("%s\n", DEFAULT_LOGFORMAT);
printf("\n");
printf("See the upslog(8) man page for more information.\n");
exit(EXIT_SUCCESS);
}
/* print current host name */
static void do_host(const char *arg)
{
int ret;
char hn[LARGEBUF];
ret = gethostname(hn, sizeof(hn));
if (ret != 0) {
upslog_with_errno(LOG_ERR, "gethostname failed");
return;
}
snprintfcat(logbuffer, sizeof(logbuffer), "%s", hn);
}
static void do_upshost(const char *arg)
{
snprintfcat(logbuffer, sizeof(logbuffer), "%s", monhost);
}
static void do_pid(const char *arg)
{
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (long)getpid());
}
static void do_time(const char *arg)
{
unsigned int i;
char timebuf[SMALLBUF], *format;
time_t tod;
format = xstrdup(arg);
/* @s are used on the command line since % is taken */
for (i = 0; i < strlen(format); i++)
if (format[i] == '@')
format[i] = '%';
time(&tod);
strftime(timebuf, sizeof(timebuf), format, localtime(&tod));
snprintfcat(logbuffer, sizeof(logbuffer), "%s", timebuf);
free(format);
}
static void getvar(const char *var)
{
int ret;
unsigned int numq, numa;
const char *query[4];
char **answer;
query[0] = "VAR";
query[1] = upsname;
query[2] = var;
numq = 3;
ret = upscli_get(&ups, numq, query, &numa, &answer);
if ((ret < 0) || (numa < numq)) {
snprintfcat(logbuffer, sizeof(logbuffer), "NA");
return;
}
snprintfcat(logbuffer, sizeof(logbuffer), "%s", answer[3]);
}
static void do_var(const char *arg)
{
if ((!arg) || (strlen(arg) < 1)) {
snprintfcat(logbuffer, sizeof(logbuffer), "INVALID");
return;
}
/* old variable names are no longer supported */
if (!strchr(arg, '.')) {
snprintfcat(logbuffer, sizeof(logbuffer), "INVALID");
return;
}
/* a UPS name is now required */
if (!upsname) {
snprintfcat(logbuffer, sizeof(logbuffer), "INVALID");
return;
}
getvar(arg);
}
static void do_etime(const char *arg)
{
time_t tod;
time(&tod);
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (unsigned long) tod);
}
static void print_literal(const char *arg)
{
snprintfcat(logbuffer, sizeof(logbuffer), "%s", arg);
}
/* register another parsing function to be called later */
static void add_call(void (*fptr)(const char *arg), const char *arg)
{
struct flist_t *tmp, *last;
tmp = last = fhead;
while (tmp) {
last = tmp;
tmp = tmp->next;
}
tmp = xmalloc(sizeof(struct flist_t));
tmp->fptr = fptr;
if (arg)
tmp->arg = xstrdup(arg);
else
tmp->arg = NULL;
tmp->next = NULL;
if (last)
last->next = tmp;
else
fhead = tmp;
}
/* turn the format string into a list of function calls with args */
static void compile_format(void)
{
unsigned int i;
int j, found, ofs;
char *cmd, *arg, *ptr;
for (i = 0; i < strlen(logformat); i++) {
/* if not a % sequence, append character and start over */
if (logformat[i] != '%') {
char buf[4];
/* we have to stuff it into a string first */
snprintf(buf, sizeof(buf), "%c", logformat[i]);
add_call(print_literal, buf);
continue;
}
/* if a %%, append % and start over */
if (logformat[i+1] == '%') {
add_call(print_literal, "%");
/* make sure we don't parse the second % next time */
i++;
continue;
}
/* it must start with a % now - %<cmd>[ <arg>]%*/
cmd = xstrdup(&logformat[i+1]);
ptr = strchr(cmd, '%');
/* no trailing % = broken */
if (!ptr) {
add_call(print_literal, "INVALID");
free(cmd);
continue;
}
*ptr = '\0';
/* remember length (plus first %) so we can skip over it */
ofs = strlen(cmd) + 1;
/* jump out to argument (if any) */
arg = strchr(cmd, ' ');
if (arg)
*arg++ = '\0';
found = 0;
/* see if we know how to handle this command */
for (j = 0; logcmds[j].name != NULL; j++) {
if (strncasecmp(cmd, logcmds[j].name,
strlen(logcmds[j].name)) == 0) {
add_call(logcmds[j].func, arg);
found = 1;
break;
}
}
free(cmd);
if (!found)
add_call(print_literal, "INVALID");
/* now do the skip ahead saved from before */
i += ofs;
} /* for (i = 0; i < strlen(logformat); i++) */
}
/* go through the list of functions and call them in order */
static void run_flist(void)
{
struct flist_t *tmp;
tmp = fhead;
memset(logbuffer, 0, sizeof(logbuffer));
while (tmp) {
tmp->fptr(tmp->arg);
tmp = tmp->next;
}
fprintf(logfile, "%s\n", logbuffer);
fflush(logfile);
}
/* -s <monhost>
* -l <log file>
* -i <interval>
* -f <format>
* -u <username>
*/
int main(int argc, char **argv)
{
int interval = 30, i;
char *prog = NULL;
time_t now, nextpoll = 0;
const char *user = NULL;
struct passwd *new_uid = NULL;
const char *pidfilebase = "upslog";
logformat = DEFAULT_LOGFORMAT;
user = RUN_AS_USER;
printf("Network UPS Tools upslog %s\n", UPS_VERSION);
prog = argv[0];
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) {
switch(i) {
case 'h':
help(prog);
break;
case 's':
monhost = optarg;
break;
case 'l':
logfn = optarg;
break;
case 'i':
interval = atoi(optarg);
break;
case 'f':
logformat = optarg;
break;
case 'u':
user = optarg;
break;
case 'V':
exit(EXIT_SUCCESS);
case 'p':
pidfilebase = optarg;
break;
}
}
argc -= optind;
argv += optind;
/* not enough args for the old way? */
if ((argc == 1) || (argc == 2))
help(prog);
/* see if it's being called in the old style - 3 or 4 args */
/* <system> <logfn> <interval> [<format>] */
if (argc >= 3) {
monhost = argv[0];
logfn = argv[1];
interval = atoi(argv[2]);
}
if (argc >= 4) {
/* read out the remaining argv entries to the format string */
logformat = xmalloc(LARGEBUF);
memset(logformat, '\0', LARGEBUF);
for (i = 3; i < argc; i++)
snprintfcat(logformat, LARGEBUF, "%s ", argv[i]);
}
if (!monhost)
fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s <system>");
if (!logfn)
fatalx(EXIT_FAILURE, "No filename defined for logging - use -l <file>");
/* shouldn't happen */
if (!logformat)
fatalx(EXIT_FAILURE, "No format defined - but this should be impossible");
printf("logging status of %s to %s (%is intervals)\n",
monhost, logfn, interval);
if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) {
fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n");
}
if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0)
fprintf(stderr, "Warning: initial connect failed: %s\n",
upscli_strerror(&ups));
if (strcmp(logfn, "-") == 0)
logfile = stdout;
else
logfile = fopen(logfn, "a");
if (logfile == NULL)
fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", logfn);
/* now drop root if we have it */
new_uid = get_user_pwent(user);
openlog("upslog", LOG_PID, LOG_FACILITY);
if (logfile != stdout)
background();
setup_signals();
writepid(pidfilebase);
become_user(new_uid);
compile_format();
while (exit_flag == 0) {
time(&now);
if (nextpoll > now) {
/* there is still time left, so sleep it off */
sleep(difftime(nextpoll, now));
nextpoll += interval;
} else {
/* we spent more time in polling than the interval allows */
nextpoll = now + interval;
}
if (reopen_flag) {
upslogx(LOG_INFO, "Signal %d: reopening log file",
reopen_flag);
reopen_log();
reopen_flag = 0;
}
/* reconnect if necessary */
if (upscli_fd(&ups) < 0) {
upscli_connect(&ups, hostname, port, 0);
}
run_flist();
/* don't keep connection open if we don't intend to use it shortly */
if (interval > 30) {
upscli_disconnect(&ups);
}
}
upslogx(LOG_INFO, "Signal %d: exiting", exit_flag);
if (logfile != stdout)
fclose(logfile);
upscli_disconnect(&ups);
exit(EXIT_SUCCESS);
}

29
clients/upslog.h Normal file
View file

@ -0,0 +1,29 @@
/* upslog.h - table of functions for handling various logging functions */
/* function list */
struct flist_t {
void (*fptr)(const char *arg);
const char *arg;
struct flist_t *next;
};
static void do_host(const char *arg);
static void do_upshost(const char *arg);
static void do_pid(const char *arg);
static void do_time(const char *arg);
static void do_var(const char *arg);
static void do_etime(const char *arg);
struct {
const char *name;
void (*func)(const char *arg);
} logcmds[] =
{
{ "HOST", do_host },
{ "UPSHOST", do_upshost },
{ "PID", do_pid },
{ "TIME", do_time },
{ "VAR", do_var },
{ "ETIME", do_etime },
{ NULL, (void(*)())(NULL) }
};

2046
clients/upsmon.c Normal file

File diff suppressed because it is too large Load diff

114
clients/upsmon.h Normal file
View file

@ -0,0 +1,114 @@
/* upsmon.h - headers and other useful things for upsmon.h
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
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
*/
/* flags for ups->status */
#define ST_ONLINE 0x001 /* UPS is on line (OL) */
#define ST_ONBATT 0x002 /* UPS is on battery (OB) */
#define ST_LOWBATT 0x004 /* UPS has a low battery (LB) */
#define ST_FSD 0x008 /* master has set forced shutdown flag */
#define ST_MASTER 0x010 /* we are the master on this UPS */
/* was ST_ALIVE 0x020 */
#define ST_LOGIN 0x040 /* we are logged into this UPS */
/* was ST_FIRST 0x080 */
#define ST_CONNECTED 0x100 /* upscli_connect returned OK */
/* required contents of flag file */
#define SDMAGIC "upsmon-shutdown-file"
/* UPS tracking structure */
typedef struct {
UPSCONN_t conn; /* upsclient state descriptor */
char *sys; /* raw system name from .conf */
char *upsname; /* just upsname */
char *hostname; /* just hostname */
int port; /* just the port */
int pv; /* power value from conf */
char *un; /* username (optional for now) */
char *pw; /* password from conf */
int status; /* status (see flags above) */
int retain; /* tracks deletions at reload */
/* handle suppression of COMMOK and ONLINE at startup */
int commstate; /* these start at -1, and only */
int linestate; /* fire on a 0->1 transition */
time_t lastpoll; /* time of last successful poll */
time_t lastnoncrit; /* time of last non-crit poll */
time_t lastrbwarn; /* time of last REPLBATT warning*/
time_t lastncwarn; /* time of last NOCOMM warning */
void *next;
} utype_t;
/* notify identifiers */
#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_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_NOPARENT 9 /* privileged parent process died */
/* notify flag values */
#define NOTIFY_IGNORE 1 /* don't do anything */
#define NOTIFY_SYSLOG 2 /* send the msg to the syslog */
#define NOTIFY_WALL 4 /* send the msg to all users */
#define NOTIFY_EXEC 8 /* send the msg to NOTIFYCMD script */
/* flags are set to NOTIFY_SYSLOG | NOTIFY_WALL at program init */
/* the user can override with NOTIFYFLAGS in the upsmon.conf */
struct {
int type;
const char *name;
char *msg; /* NULL until overridden */
const char *stockmsg;
int flags;
} notifylist[] =
{
{ NOTIFY_ONLINE, "ONLINE", NULL, "UPS %s on line power", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_ONBATT, "ONBATT", NULL, "UPS %s on battery", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_LOWBATT, "LOWBATT", NULL, "UPS %s battery is low", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_FSD, "FSD", NULL, "UPS %s: forced shutdown in progress", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_COMMOK, "COMMOK", NULL, "Communications with UPS %s established", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_COMMBAD, "COMMBAD", NULL, "Communications with UPS %s lost", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_SHUTDOWN, "SHUTDOWN", NULL, "Auto logout and shutdown proceeding", NOTIFY_SYSLOG | NOTIFY_WALL },
{ 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 },
{ 0, NULL, NULL, NULL, 0 }
};
/* values for signals passed between processes */
#define SIGCMD_FSD SIGUSR1
#define SIGCMD_STOP SIGTERM
#define SIGCMD_RELOAD SIGHUP
/* various constants */
#define NET_TIMEOUT 10 /* wait 10 seconds max for upsd to respond */

508
clients/upsrw.c Normal file
View file

@ -0,0 +1,508 @@
/* upsrw - simple client for read/write variable access (formerly upsct2)
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include <pwd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "upsclient.h"
struct list_t {
char *name;
struct list_t *next;
};
static void usage(const char *prog)
{
printf("Network UPS Tools upsrw %s\n\n", UPS_VERSION);
printf("usage: %s [-h]\n", prog);
printf(" %s [-s <variable>] [-u <username>] [-p <password>] <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(" -u <username> set username for command authentication\n");
printf(" -p <password> set password for command authentication\n");
printf("\n");
printf(" <ups> UPS identifier - <upsname>[@<hostname>[:<port>]]\n");
printf("\n");
printf("Call without -s to show all possible read/write variables.\n");
exit(EXIT_SUCCESS);
}
static void clean_exit(UPSCONN_t *ups, char *upsname, char *hostname, int code)
{
free(upsname);
free(hostname);
upscli_disconnect(ups);
exit(code);
}
static int do_set(UPSCONN_t *ups, const char *upsname, const char *varname,
const char *newval)
{
char buf[SMALLBUF], enc[SMALLBUF];
snprintf(buf, sizeof(buf), "SET VAR %s %s \"%s\"\n",
upsname, varname, pconf_encode(newval, enc, sizeof(enc)));
if (upscli_sendline(ups, buf, strlen(buf)) < 0) {
fprintf(stderr, "Can't set variable: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
if (upscli_readline(ups, buf, sizeof(buf)) < 0) {
fprintf(stderr, "Set variable failed: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
/* FUTURE: status cookies will tie in here */
if (strncmp(buf, "OK", 2) != 0) {
printf("Unexpected response from upsd: %s\n", buf);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int do_setvar(UPSCONN_t *ups, const char *varname, char *uin,
const char *pass, char *upsname, char *hostname)
{
char newval[SMALLBUF], temp[SMALLBUF], user[SMALLBUF], *ptr;
struct passwd *pw;
if (uin) {
snprintf(user, sizeof(user), "%s", uin);
} else {
memset(user, '\0', sizeof(user));
pw = getpwuid(getuid());
if (pw)
printf("Username (%s): ", pw->pw_name);
else
printf("Username: ");
if (fgets(user, sizeof(user), stdin) == NULL) {
upsdebug_with_errno(LOG_INFO, "%s", __func__);
}
/* deal with that pesky newline */
if (strlen(user) > 1)
user[strlen(user) - 1] = '\0';
else {
if (!pw)
fatalx(EXIT_FAILURE, "No username available - even tried getpwuid");
snprintf(user, sizeof(user), "%s", pw->pw_name);
}
}
/* leaks - use -p when running in valgrind */
if (!pass) {
pass = GETPASS("Password: " );
if (!pass) {
fprintf(stderr, "getpass failed: %s\n",
strerror(errno));
return EXIT_FAILURE;
}
}
/* Check if varname is in VAR=VALUE form */
if ((ptr = strchr(varname, '=')) != NULL) {
*ptr++ = 0;
snprintf(newval, sizeof(newval), "%s", ptr);
} else {
printf("Enter new value for %s: ", varname);
fflush(stdout);
if (fgets(newval, sizeof(newval), stdin) == NULL) {
upsdebug_with_errno(LOG_INFO, "%s", __func__);
}
newval[strlen(newval) - 1] = '\0';
}
snprintf(temp, sizeof(temp), "USERNAME %s\n", user);
if (upscli_sendline(ups, temp, strlen(temp)) < 0) {
fprintf(stderr, "Can't set username: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
if (upscli_readline(ups, temp, sizeof(temp)) < 0) {
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fprintf(stderr, "Set username failed due to an "
"unknown command.\n");
fprintf(stderr, "You probably need to upgrade upsd.\n");
clean_exit(ups, upsname, hostname, EXIT_FAILURE);
}
fprintf(stderr, "Set username failed: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
snprintf(temp, sizeof(temp), "PASSWORD %s\n", pass);
if (upscli_sendline(ups, temp, strlen(temp)) < 0) {
fprintf(stderr, "Can't set password: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
if (upscli_readline(ups, temp, sizeof(temp)) < 0) {
fprintf(stderr, "Set password failed: %s\n",
upscli_strerror(ups));
return EXIT_FAILURE;
}
/* no upsname means die */
if (!upsname) {
fprintf(stderr, "Error: a UPS name must be specified (upsname[@hostname[:port]])\n");
return EXIT_FAILURE;
}
/* old variable names are no longer supported */
if (!strchr(varname, '.')) {
fprintf(stderr, "Error: old variable names are not supported\n");
return EXIT_FAILURE;
}
return do_set(ups, upsname, varname, newval);
}
static const char *get_data(const char *type, UPSCONN_t *ups,
const char *upsname, const char *varname)
{
int ret;
unsigned int numq, numa;
char **answer;
const char *query[4];
query[0] = type;
query[1] = upsname;
query[2] = varname;
numq = 3;
ret = upscli_get(ups, numq, query, &numa, &answer);
if ((ret < 0) || (numa < numq))
return NULL;
/* <type> <upsname> <varname> <desc> */
return answer[3];
}
static void do_string(UPSCONN_t *ups, const char *upsname, const char *varname)
{
const char *val;
val = get_data("VAR", ups, upsname, varname);
if (!val) {
fprintf(stderr, "do_string: can't get current value of %s\n",
varname);
return;
}
printf("Type: STRING\n");
printf("Value: %s\n", val);
}
static void do_enum(UPSCONN_t *ups, const char *upsname, const char *varname)
{
int ret;
unsigned int numq, numa;
char **answer, *val;
const char *query[4], *tmp;
/* get current value */
tmp = get_data("VAR", ups, upsname, varname);
if (!tmp) {
fprintf(stderr, "do_enum: can't get current value of %s\n",
varname);
return;
}
/* tmp is a pointer into answer - have to save it somewhere else */
val = xstrdup(tmp);
query[0] = "ENUM";
query[1] = upsname;
query[2] = varname;
numq = 3;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
fprintf(stderr, "Error: %s\n", upscli_strerror(ups));
return;
}
ret = upscli_list_next(ups, numq, query, &numa, &answer);
printf("Type: ENUM\n");
while (ret == 1) {
/* ENUM <upsname> <varname> <value> */
if (numa < 4) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 4)\n", numa);
free(val);
return;
}
printf("Option: \"%s\"", answer[3]);
if (!strcmp(answer[3], val))
printf(" SELECTED");
printf("\n");
ret = upscli_list_next(ups, numq, query, &numa, &answer);
}
free(val);
}
static void do_type(UPSCONN_t *ups, const char *upsname, const char *varname)
{
int ret;
unsigned int i, numq, numa;
char **answer;
const char *query[4];
query[0] = "TYPE";
query[1] = upsname;
query[2] = varname;
numq = 3;
ret = upscli_get(ups, numq, query, &numa, &answer);
if ((ret < 0) || (numa < numq)) {
printf("Unknown type\n");
return;
}
/* TYPE <upsname> <varname> <type>... */
for (i = 3; i < numa; i++) {
if (!strcasecmp(answer[i], "ENUM")) {
do_enum(ups, upsname, varname);
return;
}
if (!strncasecmp(answer[i], "STRING:", 7)) {
do_string(ups, upsname, varname);
return;
}
/* ignore this one */
if (!strcasecmp(answer[i], "RW"))
continue;
printf("Type: %s (unrecognized)\n", answer[i]);
}
}
static void print_rw(UPSCONN_t *ups, const char *upsname, const char *varname)
{
const char *tmp;
printf("[%s]\n", varname);
tmp = get_data("DESC", ups, upsname, varname);
if (tmp)
printf("%s\n", tmp);
else
printf("Description unavailable\n");
do_type(ups, upsname, varname);
printf("\n");
}
static int print_rwlist(UPSCONN_t *ups, const char *upsname)
{
int ret;
unsigned int numq, numa;
const char *query[2];
char **answer;
struct list_t *lhead, *llast, *ltmp, *lnext;
/* the upsname is now required */
if (!upsname) {
fprintf(stderr, "Error: a UPS name must be specified (upsname[@hostname[:port]])\n");
return EXIT_FAILURE;
}
llast = lhead = NULL;
query[0] = "RW";
query[1] = upsname;
numq = 2;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
/* old upsd --> fall back on old LISTRW technique */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
fprintf(stderr, "Error: upsd is too old to support this query\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Error: %s\n", upscli_strerror(ups));
return EXIT_FAILURE;
}
ret = upscli_list_next(ups, numq, query, &numa, &answer);
while (ret == 1) {
/* RW <upsname> <varname> <value> */
if (numa < 4) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 4)\n", numa);
return EXIT_FAILURE;
}
/* sock this entry away for later */
ltmp = xmalloc(sizeof(struct list_t));
ltmp->name = xstrdup(answer[2]);
ltmp->next = NULL;
if (llast)
llast->next = ltmp;
else
lhead = ltmp;
llast = ltmp;
ret = upscli_list_next(ups, numq, query, &numa, &answer);
}
/* use the list to get descriptions and types */
ltmp = lhead;
while (ltmp) {
lnext = ltmp->next;
print_rw(ups, upsname, ltmp->name);
free(ltmp->name);
free(ltmp);
ltmp = lnext;
}
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
int i, port, ret;
char *upsname, *hostname, *setvar, *prog;
char *password = NULL, *username = NULL;
UPSCONN_t ups;
setvar = username = NULL;
prog = argv[0];
while ((i = getopt(argc, argv, "+s:p:u:V")) != -1) {
switch (i) {
case 's':
setvar = optarg;
break;
case 'p':
password = optarg;
break;
case 'u':
username = optarg;
break;
case 'V':
printf("Network UPS Tools upsrw %s\n", UPS_VERSION);
exit(EXIT_SUCCESS);
default:
usage(prog);
break;
}
}
argc -= optind;
argv += optind;
if (argc < 1)
usage(prog);
upsname = hostname = NULL;
if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) {
fprintf(stderr, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n");
clean_exit(&ups, upsname, hostname, EXIT_FAILURE);
}
if (upscli_connect(&ups, hostname, port, 0) < 0) {
fprintf(stderr, "Can't connect: %s\n", upscli_strerror(&ups));
clean_exit(&ups, upsname, hostname, EXIT_FAILURE);
}
/* setting a variable? */
if (setvar) {
ret = do_setvar(&ups, setvar, username, password, upsname,
hostname);
clean_exit(&ups, upsname, hostname, ret);
}
/* if not, get the list of supported read/write variables */
ret = print_rwlist(&ups, upsname);
clean_exit(&ups, upsname, hostname, ret);
/* NOTREACHED */
exit(EXIT_FAILURE);
}

21
clients/upssched-cmd Executable file
View file

@ -0,0 +1,21 @@
#! /bin/sh
#
# This script should be called by upssched via the CMDSCRIPT directive.
#
# Here is a quick example to show how to handle a bunch of possible
# timer names with the help of the case structure.
#
# This script may be replaced with another program without harm.
#
# The first argument passed to your CMDSCRIPT is the name of the timer
# from your AT lines.
case $1 in
upsgone)
logger -t upssched-cmd "The UPS has been gone for awhile"
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac

921
clients/upssched.c Normal file
View file

@ -0,0 +1,921 @@
/* upssched.c - upsmon's scheduling helper for offset timers
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
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
*/
/* design notes for the curious:
*
* 1. we get called with a upsname and notifytype from upsmon
* 2. the config file is searched for an AT condition that matches
* 3. the conditions on any matching lines are parsed
*
* starting a timer: the timer is added to the daemon's timer queue
* cancelling a timer: the timer is removed from that queue
* execute a command: the command is passed straight to the cmdscript
*
* if the daemon is not already running and is required (to start a timer)
* it will be started automatically
*
* when the time arrives, the command associated with a timer will be
* executed by the daemon (via the cmdscript)
*
* timers can be cancelled at any time before they trigger
*
* the daemon will shut down automatically when no more timers are active
*
*/
#include "common.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include "upssched.h"
#include "timehead.h"
typedef struct {
char *name;
time_t etime;
void *next;
} ttype_t;
ttype_t *thead = NULL;
static struct conn_t *connhead = NULL;
char *cmdscript = NULL, *pipefn = NULL, *lockfn = NULL;
int verbose = 0; /* use for debugging */
/* ups name and notify type (string) as received from upsmon */
const char *upsname, *notify_type;
#define PARENT_STARTED -2
#define PARENT_UNNECESSARY -3
#define MAX_TRIES 30
#define EMPTY_WAIT 15 /* min passes with no timers to exit */
#define US_LISTEN_BACKLOG 16
#define US_SOCK_BUF_LEN 256
#define US_MAX_READ 128
/* --- server functions --- */
static void exec_cmd(const char *cmd)
{
int err;
char buf[LARGEBUF];
snprintf(buf, sizeof(buf), "%s %s", cmdscript, cmd);
err = system(buf);
if (WIFEXITED(err)) {
if (WEXITSTATUS(err)) {
upslogx(LOG_INFO, "exec_cmd(%s) returned %d", buf, WEXITSTATUS(err));
}
} else {
if (WIFSIGNALED(err)) {
upslogx(LOG_WARNING, "exec_cmd(%s) terminated with signal %d", buf, WTERMSIG(err));
} else {
upslogx(LOG_ERR, "Execute command failure: %s", buf);
}
}
return;
}
static void removetimer(ttype_t *tfind)
{
ttype_t *tmp, *last;
last = NULL;
tmp = thead;
while (tmp) {
if (tmp == tfind) { /* found it */
if (last == NULL) /* deleting first */
thead = tmp->next;
else
last->next = tmp->next;
free(tmp->name);
free(tmp);
return;
}
last = tmp;
tmp = tmp->next;
}
/* this one should never happen */
upslogx(LOG_ERR, "removetimer: failed to locate target at %p", (void *)tfind);
}
static void checktimers(void)
{
ttype_t *tmp, *tmpnext;
time_t now;
static int emptyctr = 0;
/* if the queue is empty we might be ready to exit */
if (!thead) {
emptyctr++;
/* wait a little while in case someone wants us again */
if (emptyctr < EMPTY_WAIT)
return;
if (verbose)
upslogx(LOG_INFO, "Timer queue empty, exiting");
#ifdef UPSSCHED_RACE_TEST
upslogx(LOG_INFO, "triggering race: sleeping 15 sec before exit");
sleep(15);
#endif
unlink(pipefn);
exit(EXIT_SUCCESS);
}
emptyctr = 0;
/* flip through LL, look for activity */
tmp = thead;
time(&now);
while (tmp) {
tmpnext = tmp->next;
if (now >= tmp->etime) {
if (verbose)
upslogx(LOG_INFO, "Event: %s ", tmp->name);
exec_cmd(tmp->name);
/* delete from queue */
removetimer(tmp);
}
tmp = tmpnext;
}
}
static void start_timer(const char *name, const char *ofsstr)
{
time_t now;
int ofs;
ttype_t *tmp, *last;
/* get the time */
time(&now);
/* add an event for <now> + <time> */
ofs = strtol(ofsstr, (char **) NULL, 10);
if (ofs < 0) {
upslogx(LOG_INFO, "bogus offset for timer, ignoring");
return;
}
if (verbose)
upslogx(LOG_INFO, "New timer: %s (%d seconds)", name, ofs);
/* now add to the queue */
tmp = last = thead;
while (tmp) {
last = tmp;
tmp = tmp->next;
}
tmp = xmalloc(sizeof(ttype_t));
tmp->name = xstrdup(name);
tmp->etime = now + ofs;
tmp->next = NULL;
if (last)
last->next = tmp;
else
thead = tmp;
}
static void cancel_timer(const char *name, const char *cname)
{
ttype_t *tmp;
for (tmp = thead; tmp != NULL; tmp = tmp->next) {
if (!strcmp(tmp->name, name)) { /* match */
if (verbose)
upslogx(LOG_INFO, "Cancelling timer: %s", name);
removetimer(tmp);
return;
}
}
/* this is not necessarily an error */
if (cname && cname[0]) {
if (verbose)
upslogx(LOG_INFO, "Cancel %s, event: %s", name, cname);
exec_cmd(cname);
}
}
static void us_serialize(int op)
{
static int pipefd[2];
int ret;
char ch;
switch(op) {
case SERIALIZE_INIT:
ret = pipe(pipefd);
if (ret != 0)
fatal_with_errno(EXIT_FAILURE, "serialize: pipe");
break;
case SERIALIZE_SET:
close(pipefd[0]);
close(pipefd[1]);
break;
case SERIALIZE_WAIT:
close(pipefd[1]);
ret = read(pipefd[0], &ch, 1);
close(pipefd[0]);
break;
}
}
static int open_sock(void)
{
int ret, fd;
struct sockaddr_un ssaddr;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
fatal_with_errno(EXIT_FAILURE, "Can't create a unix domain socket");
ssaddr.sun_family = AF_UNIX;
snprintf(ssaddr.sun_path, sizeof(ssaddr.sun_path), "%s", pipefn);
unlink(pipefn);
umask(0007);
ret = bind(fd, (struct sockaddr *) &ssaddr, sizeof ssaddr);
if (ret < 0)
fatal_with_errno(EXIT_FAILURE, "bind %s failed", pipefn);
ret = chmod(pipefn, 0660);
if (ret < 0)
fatal_with_errno(EXIT_FAILURE, "chmod(%s, 0660) failed", pipefn);
ret = listen(fd, US_LISTEN_BACKLOG);
if (ret < 0)
fatal_with_errno(EXIT_FAILURE, "listen(%d, %d) failed", fd, US_LISTEN_BACKLOG);
return fd;
}
static void conn_del(struct conn_t *target)
{
struct conn_t *tmp, *last = NULL;
tmp = connhead;
while (tmp) {
if (tmp == target) {
if (last)
last->next = tmp->next;
else
connhead = tmp->next;
pconf_finish(&tmp->ctx);
free(tmp);
return;
}
last = tmp;
tmp = tmp->next;
}
upslogx(LOG_ERR, "Tried to delete a bogus state connection");
}
static int send_to_one(struct conn_t *conn, const char *fmt, ...)
{
int ret;
va_list ap;
char buf[US_SOCK_BUF_LEN];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ret = write(conn->fd, buf, strlen(buf));
if ((ret < 1) || (ret != (int) strlen(buf))) {
upsdebugx(2, "write to fd %d failed", conn->fd);
close(conn->fd);
conn_del(conn);
return 0; /* failed */
}
return 1; /* OK */
}
static void conn_add(int sockfd)
{
int acc, ret;
struct conn_t *tmp, *last;
struct sockaddr_un saddr;
socklen_t salen;
salen = sizeof(saddr);
acc = accept(sockfd, (struct sockaddr *) &saddr, &salen);
if (acc < 0) {
upslog_with_errno(LOG_ERR, "accept on unix fd failed");
return;
}
/* enable nonblocking I/O */
ret = fcntl(acc, F_GETFL, 0);
if (ret < 0) {
upslog_with_errno(LOG_ERR, "fcntl get on unix fd failed");
close(acc);
return;
}
ret = fcntl(acc, F_SETFL, ret | O_NDELAY);
if (ret < 0) {
upslog_with_errno(LOG_ERR, "fcntl set O_NDELAY on unix fd failed");
close(acc);
return;
}
tmp = last = connhead;
while (tmp) {
last = tmp;
tmp = tmp->next;
}
tmp = xmalloc(sizeof(struct conn_t));
tmp->fd = acc;
tmp->next = NULL;
if (last)
last->next = tmp;
else
connhead = tmp;
upsdebugx(3, "new connection on fd %d", acc);
pconf_init(&tmp->ctx, NULL);
}
static int sock_arg(struct conn_t *conn)
{
if (conn->ctx.numargs < 1)
return 0;
/* CANCEL <name> [<cmd>] */
if (!strcmp(conn->ctx.arglist[0], "CANCEL")) {
if (conn->ctx.numargs < 3)
cancel_timer(conn->ctx.arglist[1], NULL);
else
cancel_timer(conn->ctx.arglist[1], conn->ctx.arglist[2]);
send_to_one(conn, "OK\n");
return 1;
}
if (conn->ctx.numargs < 3)
return 0;
/* START <name> <length> */
if (!strcmp(conn->ctx.arglist[0], "START")) {
start_timer(conn->ctx.arglist[1], conn->ctx.arglist[2]);
send_to_one(conn, "OK\n");
return 1;
}
/* unknown */
return 0;
}
static void log_unknown(int numarg, char **arg)
{
int i;
upslogx(LOG_INFO, "Unknown command on socket: ");
for (i = 0; i < numarg; i++)
upslogx(LOG_INFO, "arg %d: %s", i, arg[i]);
}
static int sock_read(struct conn_t *conn)
{
int i, ret;
char ch;
for (i = 0; i < US_MAX_READ; i++) {
ret = read(conn->fd, &ch, 1);
if (ret < 1) {
/* short read = no parsing, come back later */
if ((ret == -1) && (errno == EAGAIN))
return 0;
/* some other problem */
return -1; /* error */
}
ret = pconf_char(&conn->ctx, ch);
if (ret == 0) /* nothing to parse yet */
continue;
if (ret == -1) {
upslogx(LOG_NOTICE, "Parse error on sock: %s",
conn->ctx.errmsg);
return 0; /* nothing parsed */
}
/* try to use it, and complain about unknown commands */
if (!sock_arg(conn)) {
log_unknown(conn->ctx.numargs, conn->ctx.arglist);
send_to_one(conn, "ERR UNKNOWN\n");
}
return 1; /* we did some work */
}
return 0; /* fell out without parsing anything */
}
static void start_daemon(int lockfd)
{
int maxfd, pid, pipefd, ret;
struct timeval tv;
fd_set rfds;
struct conn_t *tmp, *tmpnext;
socklen_t fromlen;
fromlen = sizeof(struct sockaddr);
us_serialize(SERIALIZE_INIT);
if ((pid = fork()) < 0)
fatal_with_errno(EXIT_FAILURE, "Unable to enter background");
if (pid != 0) { /* parent */
/* wait for child to set up the listener */
us_serialize(SERIALIZE_WAIT);
return;
}
/* child */
close(0);
close(1);
close(2);
/* make fds 0-2 point somewhere defined */
if (open("/dev/null", O_RDWR) != 0)
fatal_with_errno(EXIT_FAILURE, "open /dev/null");
if (dup(0) == -1)
fatal_with_errno(EXIT_FAILURE, "dup");
if (dup(0) == -1)
fatal_with_errno(EXIT_FAILURE, "dup");
pipefd = open_sock();
if (verbose)
upslogx(LOG_INFO, "Timer daemon started");
/* release the parent */
us_serialize(SERIALIZE_SET);
/* drop the lock now that the background is running */
unlink(lockfn);
close(lockfd);
/* now watch for activity */
for (;;) {
/* wait at most 1s so we can check our timers regularly */
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(pipefd, &rfds);
maxfd = pipefd;
for (tmp = connhead; tmp != NULL; tmp = tmp->next) {
FD_SET(tmp->fd, &rfds);
if (tmp->fd > maxfd)
maxfd = tmp->fd;
}
ret = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if (ret > 0) {
if (FD_ISSET(pipefd, &rfds))
conn_add(pipefd);
tmp = connhead;
while (tmp) {
tmpnext = tmp->next;
if (FD_ISSET(tmp->fd, &rfds)) {
if (sock_read(tmp) < 0) {
close(tmp->fd);
conn_del(tmp);
}
}
tmp = tmpnext;
}
}
checktimers();
}
}
/* --- 'client' functions --- */
static int try_connect(void)
{
int pipefd, ret;
struct sockaddr_un saddr;
memset(&saddr, '\0', sizeof(saddr));
saddr.sun_family = AF_UNIX;
snprintf(saddr.sun_path, sizeof(saddr.sun_path), "%s", pipefn);
pipefd = socket(AF_UNIX, SOCK_STREAM, 0);
if (pipefd < 0)
fatal_with_errno(EXIT_FAILURE, "socket");
ret = connect(pipefd, (const struct sockaddr *) &saddr, sizeof(saddr));
if (ret != -1)
return pipefd;
return -1;
}
static int get_lock(const char *fn)
{
return open(fn, O_RDONLY | O_CREAT | O_EXCL, 0);
}
/* try to connect to bg process, and start one if necessary */
static int check_parent(const char *cmd, const char *arg2)
{
int pipefd, lockfd, tries = 0;
for (tries = 0; tries < MAX_TRIES; tries++) {
pipefd = try_connect();
if (pipefd != -1)
return pipefd;
/* timer daemon isn't running */
/* it's not running, so there's nothing to cancel */
if (!strcmp(cmd, "CANCEL") && (arg2 == NULL))
return PARENT_UNNECESSARY;
/* arg2 non-NULL means there is a cancel action available */
/* we need to start the daemon, so try to get the lock */
lockfd = get_lock(lockfn);
if (lockfd != -1) {
start_daemon(lockfd);
return PARENT_STARTED; /* started successfully */
}
/* we didn't get the lock - must be two upsscheds running */
/* blow this away in case we crashed before */
unlink(lockfn);
/* give the other one a chance to start it, then try again */
usleep(250000);
}
upslog_with_errno(LOG_ERR, "Failed to connect to parent and failed to create parent");
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];
/* insanity */
if (!arg1)
return;
/* build the request */
snprintf(buf, sizeof(buf), "%s \"%s\"",
cmd, pconf_encode(arg1, enc, sizeof(enc)));
if (arg2)
snprintfcat(buf, sizeof(buf), " \"%s\"",
pconf_encode(arg2, enc, sizeof(enc)));
snprintfcat(buf, sizeof(buf), "\n");
/* see if the parent needs to be started (and maybe start it) */
for (i = 0; i < MAX_TRIES; i++) {
pipefd = check_parent(cmd, arg2);
if (pipefd == PARENT_STARTED) {
/* loop back and try to connect now */
usleep(250000);
continue;
}
/* special case for CANCEL when no parent is running */
if (pipefd == PARENT_UNNECESSARY)
return;
/* we're connected now */
ret = write(pipefd, buf, strlen(buf));
/* if we can't send the whole thing, loop back and try again */
if ((ret < 1) || (ret != (int) strlen(buf))) {
upslogx(LOG_ERR, "write failed, trying again");
close(pipefd);
continue;
}
/* ugh - probably should use select here... */
setup_sigalrm();
alarm(2);
ret = read(pipefd, buf, sizeof(buf));
alarm(0);
signal(SIGALRM, SIG_IGN);
close(pipefd);
/* same idea: no OK = go try it all again */
if (ret < 2) {
upslogx(LOG_ERR, "read confirmation failed, trying again");
continue;
}
if (!strncmp(buf, "OK", 2))
return; /* success */
upslogx(LOG_ERR, "read confirmation got [%s]", buf);
/* try again ... */
}
fatalx(EXIT_FAILURE, "Unable to connect to daemon and unable to start daemon");
}
static void parse_at(const char *ntype, const char *un, const char *cmd,
const char *ca1, const char *ca2)
{
/* complain both ways in case we don't have a tty */
if (!cmdscript) {
printf("CMDSCRIPT must be set before any ATs in the config file!\n");
fatalx(EXIT_FAILURE, "CMDSCRIPT must be set before any ATs in the config file!");
}
if (!pipefn) {
printf("PIPEFN must be set before any ATs in the config file!\n");
fatalx(EXIT_FAILURE, "PIPEFN must be set before any ATs in the config file!");
}
if (!lockfn) {
printf("LOCKFN must be set before any ATs in the config file!\n");
fatalx(EXIT_FAILURE, "LOCKFN must be set before any ATs in the config file!");
}
/* check upsname: does this apply to us? */
if (strcmp(upsname, un) != 0)
if (strcmp(un, "*") != 0)
return; /* not for us, and not the wildcard */
/* see if the current notify type matches the one from the .conf */
if (strcasecmp(notify_type, ntype) != 0)
return;
/* if command is valid, send it to the daemon (which may start it) */
if (!strcmp(cmd, "START-TIMER")) {
sendcmd("START", ca1, ca2);
return;
}
if (!strcmp(cmd, "CANCEL-TIMER")) {
sendcmd("CANCEL", ca1, ca2);
return;
}
if (!strcmp(cmd, "EXECUTE")) {
if (ca1 == '\0') {
upslogx(LOG_ERR, "Empty EXECUTE command argument");
return;
}
if (verbose)
upslogx(LOG_INFO, "Executing command: %s", ca1);
exec_cmd(ca1);
return;
}
upslogx(LOG_ERR, "Invalid command: %s", cmd);
}
static int conf_arg(int numargs, char **arg)
{
if (numargs < 2)
return 0;
/* CMDSCRIPT <scriptname> */
if (!strcmp(arg[0], "CMDSCRIPT")) {
cmdscript = xstrdup(arg[1]);
return 1;
}
/* PIPEFN <pipename> */
if (!strcmp(arg[0], "PIPEFN")) {
pipefn = xstrdup(arg[1]);
return 1;
}
/* LOCKFN <filename> */
if (!strcmp(arg[0], "LOCKFN")) {
lockfn = xstrdup(arg[1]);
return 1;
}
if (numargs < 5)
return 0;
/* AT <notifytype> <upsname> <command> <cmdarg1> [<cmdarg2>] */
if (!strcmp(arg[0], "AT")) {
/* don't use arg[5] unless we have it... */
if (numargs > 5)
parse_at(arg[1], arg[2], arg[3], arg[4], arg[5]);
else
parse_at(arg[1], arg[2], arg[3], arg[4], NULL);
return 1;
}
return 0;
}
/* called for fatal errors in parseconf like malloc failures */
static void upssched_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf(upssched.conf): %s", errmsg);
}
static void checkconf(void)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
snprintf(fn, sizeof(fn), "%s/upssched.conf", confpath());
pconf_init(&ctx, upssched_err);
if (!pconf_file_begin(&ctx, fn)) {
pconf_finish(&ctx);
fatalx(EXIT_FAILURE, "%s", ctx.errmsg);
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
if (ctx.numargs < 1)
continue;
if (!conf_arg(ctx.numargs, ctx.arglist)) {
unsigned int i;
char errmsg[SMALLBUF];
snprintf(errmsg, sizeof(errmsg),
"upssched.conf: invalid directive");
for (i = 0; i < ctx.numargs; i++)
snprintfcat(errmsg, sizeof(errmsg), " %s",
ctx.arglist[i]);
upslogx(LOG_WARNING, "%s", errmsg);
}
}
pconf_finish(&ctx);
}
int main(int argc, char **argv)
{
verbose = 1; /* TODO: remove when done testing */
/* normally we don't have stderr, so get this going to syslog early */
openlog("upssched", LOG_PID, LOG_DAEMON);
syslogbit_set();
upsname = getenv("UPSNAME");
notify_type = getenv("NOTIFYTYPE");
if ((!upsname) || (!notify_type)) {
printf("Error: UPSNAME and NOTIFYTYPE must be set.\n");
printf("This program should only be run from upsmon.\n");
exit(EXIT_FAILURE);
}
/* see if this matches anything in the config file */
checkconf();
exit(EXIT_SUCCESS);
}

14
clients/upssched.h Normal file
View file

@ -0,0 +1,14 @@
/* upssched.h - supporting structures */
#include <parseconf.h>
#define SERIALIZE_INIT 1
#define SERIALIZE_SET 2
#define SERIALIZE_WAIT 3
/* track client connections */
struct conn_t {
int fd;
PCONF_CTX_t ctx;
void *next;
};

1079
clients/upsset.c Normal file

File diff suppressed because it is too large Load diff

1067
clients/upsstats.c Normal file

File diff suppressed because it is too large Load diff

24
clients/upsstats.h Normal file
View file

@ -0,0 +1,24 @@
/* upsstats.h - structures for upsstats
Copyright (C) 2002 Russell Kroll <rkroll@exploits.org>
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
*/
typedef struct {
char *sys;
char *desc;
void *next;
} ulist_t;

15
common/Makefile.am Normal file
View file

@ -0,0 +1,15 @@
# Network UPS Tools: common
AM_CFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = common.c state.c upsconf.c ../include/nut_version.h
libcommon_a_LIBADD = libparseconf.la
../include/nut_version.h: FORCE
(cd ../include/ && $(MAKE) $(AM_MAKEFLAGS) nut_version.h)
FORCE:
noinst_LTLIBRARIES = libparseconf.la
libparseconf_la_SOURCES = parseconf.c

555
common/Makefile.in Normal file
View file

@ -0,0 +1,555 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# Network UPS Tools: common
VPATH = @srcdir@
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 = common
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
libcommon_a_AR = $(AR) $(ARFLAGS)
libcommon_a_DEPENDENCIES = libparseconf.la
am_libcommon_a_OBJECTS = common.$(OBJEXT) state.$(OBJEXT) \
upsconf.$(OBJEXT)
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libparseconf_la_LIBADD =
am_libparseconf_la_OBJECTS = parseconf.lo
libparseconf_la_OBJECTS = $(am_libparseconf_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libcommon_a_SOURCES) $(libparseconf_la_SOURCES)
DIST_SOURCES = $(libcommon_a_SOURCES) $(libparseconf_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
AM_CFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = common.c state.c upsconf.c ../include/nut_version.h
libcommon_a_LIBADD = libparseconf.la
noinst_LTLIBRARIES = libparseconf.la
libparseconf_la_SOURCES = parseconf.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(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 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);; \
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):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES)
-rm -f libcommon.a
$(libcommon_a_AR) libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD)
$(RANLIB) libcommon.a
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libparseconf.la: $(libparseconf_la_OBJECTS) $(libparseconf_la_DEPENDENCIES)
$(LINK) $(libparseconf_la_OBJECTS) $(libparseconf_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseconf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsconf.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(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 $(LIBRARIES) $(LTLIBRARIES)
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:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
clean-noinstLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
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 -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLIBRARIES clean-noinstLTLIBRARIES \
ctags 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 uninstall uninstall-am
../include/nut_version.h: FORCE
(cd ../include/ && $(MAKE) $(AM_MAKEFLAGS) nut_version.h)
FORCE:
# 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:

540
common/common.c Normal file
View file

@ -0,0 +1,540 @@
/* common.c - common useful functions
Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include <ctype.h>
#include <syslog.h>
#include <pwd.h>
#include <grp.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
on nut_version_macro.h), and also to prevent all sources from
having to be recompiled each time the version changes (they only
need to be re-linked). */
#include "nut_version.h"
const char *UPS_VERSION = NUT_VERSION_MACRO;
int nut_debug_level = 0;
static int upslog_flags = UPSLOG_STDERR;
static void xbit_set(int *val, int flag)
{
*val = (*val |= flag);
}
static void xbit_clear(int *val, int flag)
{
*val = (*val ^= (*val & flag));
}
static int xbit_test(int val, int flag)
{
return ((val & flag) == flag);
}
/* enable writing upslog_with_errno() and upslogx() type messages to
the syslog */
void syslogbit_set(void)
{
xbit_set(&upslog_flags, UPSLOG_SYSLOG);
}
/* get the syslog ready for us */
void open_syslog(const char *progname)
{
int opt;
opt = LOG_PID;
/* we need this to grab /dev/log before chroot */
#ifdef LOG_NDELAY
opt |= LOG_NDELAY;
#endif
openlog(progname, opt, LOG_FACILITY);
}
/* close ttys and become a daemon */
void background(void)
{
int pid;
if ((pid = fork()) < 0)
fatal_with_errno(EXIT_FAILURE, "Unable to enter background");
xbit_set(&upslog_flags, UPSLOG_SYSLOG);
xbit_clear(&upslog_flags, UPSLOG_STDERR);
close(0);
close(1);
close(2);
if (pid != 0)
_exit(EXIT_SUCCESS); /* parent */
/* child */
/* make fds 0-2 point somewhere defined */
if (open("/dev/null", O_RDWR) != 0)
fatal_with_errno(EXIT_FAILURE, "open /dev/null");
if (dup(0) == -1)
fatal_with_errno(EXIT_FAILURE, "dup");
if (dup(0) == -1)
fatal_with_errno(EXIT_FAILURE, "dup");
#ifdef HAVE_SETSID
setsid(); /* make a new session to dodge signals */
#endif
upslogx(LOG_INFO, "Startup successful");
}
/* do this here to keep pwd/grp stuff out of the main files */
struct passwd *get_user_pwent(const char *name)
{
struct passwd *r;
errno = 0;
if ((r = getpwnam(name)))
return r;
/* POSIX does not specify that "user not found" is an error, so
some implementations of getpwnam() do not set errno when this
happens. */
if (errno == 0)
fatalx(EXIT_FAILURE, "user %s not found", name);
else
fatal_with_errno(EXIT_FAILURE, "getpwnam(%s)", name);
return NULL; /* to make the compiler happy */
}
/* change to the user defined in the struct */
void become_user(struct passwd *pw)
{
/* if we can't switch users, then don't even try */
if ((geteuid() != 0) && (getuid() != 0))
return;
if (getuid() == 0)
if (seteuid(0))
fatal_with_errno(EXIT_FAILURE, "getuid gave 0, but seteuid(0) failed");
if (initgroups(pw->pw_name, pw->pw_gid) == -1)
fatal_with_errno(EXIT_FAILURE, "initgroups");
if (setgid(pw->pw_gid) == -1)
fatal_with_errno(EXIT_FAILURE, "setgid");
if (setuid(pw->pw_uid) == -1)
fatal_with_errno(EXIT_FAILURE, "setuid");
}
/* drop down into a directory and throw away pointers to the old path */
void chroot_start(const char *path)
{
if (chdir(path))
fatal_with_errno(EXIT_FAILURE, "chdir(%s)", path);
if (chroot(path))
fatal_with_errno(EXIT_FAILURE, "chroot(%s)", path);
if (chdir("/"))
fatal_with_errno(EXIT_FAILURE, "chdir(/)");
upsdebugx(1, "chrooted into %s", path);
}
/* drop off a pidfile for this process */
void writepid(const char *name)
{
char fn[SMALLBUF];
FILE *pidf;
int mask;
/* use full path if present, else build filename in PIDPATH */
if (*name == '/')
snprintf(fn, sizeof(fn), "%s", name);
else
snprintf(fn, sizeof(fn), "%s/%s.pid", PIDPATH, name);
mask = umask(022);
pidf = fopen(fn, "w");
if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
fclose(pidf);
} else {
upslog_with_errno(LOG_NOTICE, "writepid: fopen %s", fn);
}
umask(mask);
}
/* open pidfn, get the pid, then send it sig */
int sendsignalfn(const char *pidfn, int sig)
{
char buf[SMALLBUF];
FILE *pidf;
int pid, 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);
return -1;
}
pid = strtol(buf, (char **)NULL, 10);
if (pid < 2) {
upslogx(LOG_NOTICE, "Ignoring invalid pid number %d", pid);
return -1;
}
/* see if this is going to work first */
ret = kill(pid, 0);
if (ret < 0) {
perror("kill");
return -1;
}
/* now actually send it */
ret = kill(pid, sig);
if (ret < 0) {
perror("kill");
return -1;
}
return 0;
}
int snprintfcat(char *dst, size_t size, const char *fmt, ...)
{
va_list ap;
size_t len = strlen(dst);
int ret;
size--;
assert(len <= size);
va_start(ap, fmt);
ret = vsnprintf(dst + len, size - len, fmt, ap);
va_end(ap);
dst[size] = '\0';
return len + ret;
}
/* lazy way to send a signal if the program uses the PIDPATH */
int sendsignal(const char *progname, int sig)
{
char fn[SMALLBUF];
snprintf(fn, sizeof(fn), "%s/%s.pid", PIDPATH, progname);
return sendsignalfn(fn, sig);
}
const char *xbasename(const char *file)
{
const char *p = strrchr(file, '/');
if (p == NULL)
return file;
return p + 1;
}
static void vupslog(int priority, const char *fmt, va_list va, int use_strerror)
{
int ret;
char buf[LARGEBUF];
ret = vsnprintf(buf, sizeof(buf), fmt, va);
if ((ret < 0) || (ret >= (int) sizeof(buf)))
syslog(LOG_WARNING, "vupslog: vsnprintf needed more than %d bytes",
LARGEBUF);
if (use_strerror)
snprintfcat(buf, sizeof(buf), ": %s", strerror(errno));
if (nut_debug_level > 0) {
static struct timeval start = { 0 };
struct timeval now;
gettimeofday(&now, NULL);
if (start.tv_sec == 0) {
start = now;
}
if (start.tv_usec > now.tv_usec) {
now.tv_usec += 1000000;
now.tv_sec -= 1;
}
fprintf(stderr, "%4.0f.%06ld\t", difftime(now.tv_sec, start.tv_sec), (long)(now.tv_usec - start.tv_usec));
}
if (xbit_test(upslog_flags, UPSLOG_STDERR))
fprintf(stderr, "%s\n", buf);
if (xbit_test(upslog_flags, UPSLOG_SYSLOG))
syslog(priority, "%s", buf);
}
/* Return the default path for the directory containing configuration files */
const char * confpath(void)
{
const char * path;
if ((path = getenv("NUT_CONFPATH")) == NULL)
path = CONFPATH;
return path;
}
/* Return the default path for the directory containing state files */
const char * dflt_statepath(void)
{
const char * path;
if ((path = getenv("NUT_STATEPATH")) == NULL)
path = STATEPATH;
return path;
}
/* Return the alternate path for pid files */
const char * altpidpath(void)
{
#ifdef ALTPIDPATH
return ALTPIDPATH;
#else
return dflt_statepath();
#endif
}
/* 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);
vupslog(priority, fmt, va, 1);
va_end(va);
}
/* logs the formatted string to any configured logging devices */
void upslogx(int priority, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vupslog(priority, fmt, va, 0);
va_end(va);
}
void upsdebug_with_errno(int level, const char *fmt, ...)
{
va_list va;
if (nut_debug_level < level)
return;
va_start(va, fmt);
vupslog(LOG_DEBUG, fmt, va, 1);
va_end(va);
}
void upsdebugx(int level, const char *fmt, ...)
{
va_list va;
if (nut_debug_level < level)
return;
va_start(va, fmt);
vupslog(LOG_DEBUG, fmt, va, 0);
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)
{
char line[100];
int n; /* number of characters currently in line */
int i; /* number of bytes output from buffer */
n = snprintf(line, sizeof(line), "%s: (%d bytes) =>", msg, len);
for (i = 0; i < len; i++) {
if (n > 72) {
upsdebugx(level, "%s", line);
line[0] = 0;
}
n = snprintfcat(line, sizeof(line), n ? " %02x" : "%02x",
((unsigned char *)buf)[i]);
}
upsdebugx(level, "%s", line);
}
static void vfatal(const char *fmt, va_list va, int use_strerror)
{
if (xbit_test(upslog_flags, UPSLOG_STDERR_ON_FATAL))
xbit_set(&upslog_flags, UPSLOG_STDERR);
if (xbit_test(upslog_flags, UPSLOG_SYSLOG_ON_FATAL))
xbit_set(&upslog_flags, UPSLOG_SYSLOG);
vupslog(LOG_ERR, fmt, va, use_strerror);
}
void fatal_with_errno(int status, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vfatal(fmt, va, (errno > 0) ? 1 : 0);
va_end(va);
exit(status);
}
void fatalx(int status, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vfatal(fmt, va, 0);
va_end(va);
exit(status);
}
static const char *oom_msg = "Out of memory";
void *xmalloc(size_t size)
{
void *p = malloc(size);
if (p == NULL)
fatal_with_errno(EXIT_FAILURE, "%s", oom_msg);
return p;
}
void *xcalloc(size_t number, size_t size)
{
void *p = calloc(number, size);
if (p == NULL)
fatal_with_errno(EXIT_FAILURE, "%s", oom_msg);
return p;
}
void *xrealloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (p == NULL)
fatal_with_errno(EXIT_FAILURE, "%s", oom_msg);
return p;
}
char *xstrdup(const char *string)
{
char *p = strdup(string);
if (p == NULL)
fatal_with_errno(EXIT_FAILURE, "%s", oom_msg);
return p;
}
/* modify in - strip all trailing instances of <sep> */
char *rtrim(char *in, const char sep)
{
char *p;
p = &in[strlen(in) - 1];
while ((p >= in) && (*p == sep))
*p-- = '\0';
return in;
}
/* 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)
{
int ret;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = d_sec;
tv.tv_usec = d_usec;
ret = select(fd + 1, &fds, NULL, NULL, &tv);
if (ret < 1) {
return ret;
}
return read(fd, buf, buflen);
}
/* 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)
{
int ret;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = d_sec;
tv.tv_usec = d_usec;
ret = select(fd + 1, NULL, &fds, NULL, &tv);
if (ret < 1) {
return ret;
}
return write(fd, buf, buflen);
}

616
common/parseconf.c Normal file
View file

@ -0,0 +1,616 @@
/* parseconf.c - state machine-driven dynamic configuration file parser
Copyright (C) 2002 Russell Kroll <rkroll@exploits.org>
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
*/
/* parseconf, version 4.
*
* This one abandons the "callback" system introduced last time. It
* didn't turn out as well as I had hoped - you got stuck "behind"
* parseconf too often.
*
* There is now a context buffer, and you call pconf_init to set it up.
* All subsequent calls must have it as the first argument. There are
* two entry points for parsing lines. You can have it read a file
* (pconf_file_begin and pconf_file_next), take lines directly from
* the caller (pconf_line), or go along a character at a time (pconf_char).
* The parsing is identical no matter how you feed it.
*
* Since there are no more callbacks, you take the successful return
* from the function and access ctx->arglist and ctx->numargs yourself.
* You must check for errors with pconf_parse_error before using them,
* since it might not be complete. This lets the caller handle all
* error reporting that's nonfatal.
*
* Fatal errors are those that involve memory allocation. If the user
* defines an error handler when calling pconf_init, that function will
* be called with the error message before parseconf exits. By default
* it will just write the message to stderr before exiting.
*
* Input vs. Output:
*
* What it reads --> What ends up in each argument
*
* this is a line --> "this" "is" "a" "line"
* this "is also" a line --> "this" "is also" "a" "line"
* embedded\ space --> "embedded space"
* embedded\\backslash --> "embedded\backslash"
*
* Arguments are split by whitespace (isspace()) unless that whitespace
* occurs inside a "quoted pair like this".
*
* You can also escape the double quote (") character. The backslash
* also allows you to join lines, allowing you to have logical lines
* that span physical lines, just like you can do in some shells.
*
* Lines normally end with a newline, but reaching EOF will also force
* parsing on what's been scanned so far.
*
* Design:
*
* Characters are read one at a time to drive the state machine.
* As words are completed (by hitting whitespace or ending a "" item),
* they are committed to the next buffer in the arglist. realloc is
* used, so the buffer can grow to handle bigger words.
*
* The arglist also grows as necessary with a similar approach. As a
* result, you can parse extremely long words and lines with an insane
* number of elements.
*
* Finally, there is argsize, which remembers how long each of the
* arglist elements are. This is how we know when to expand them.
*
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "parseconf.h"
/* possible states */
#define STATE_FINDWORDSTART 1
#define STATE_FINDEOL 2
#define STATE_QUOTECOLLECT 3
#define STATE_QC_LITERAL 4
#define STATE_COLLECT 5
#define STATE_COLLECTLITERAL 6
#define STATE_ENDOFLINE 7
#define STATE_PARSEERR 8
static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt)
{
if (ctx->errhandler)
ctx->errhandler(errtxt);
else
fprintf(stderr, "parseconf: fatal error: %s\n", errtxt);
exit(EXIT_FAILURE);
}
static void add_arg_word(PCONF_CTX_t *ctx)
{
int argpos;
size_t wbuflen;
/* this is where the new value goes */
argpos = ctx->numargs;
ctx->numargs++;
/* when facing more args than ever before, expand the list */
if (ctx->numargs > ctx->maxargs) {
ctx->maxargs = ctx->numargs;
/* resize the lists */
ctx->arglist = realloc(ctx->arglist,
sizeof(char *) * ctx->numargs);
if (!ctx->arglist)
pconf_fatal(ctx, "realloc arglist failed");
ctx->argsize = realloc(ctx->argsize,
sizeof(int *) * ctx->numargs);
if (!ctx->argsize)
pconf_fatal(ctx, "realloc argsize failed");
/* ensure sane starting values */
ctx->arglist[argpos] = NULL;
ctx->argsize[argpos] = 0;
}
wbuflen = strlen(ctx->wordbuf);
/* now see if the string itself grew compared to last time */
if (wbuflen >= ctx->argsize[argpos]) {
size_t newlen;
/* allow for the trailing NULL */
newlen = wbuflen + 1;
/* expand the string storage */
ctx->arglist[argpos] = realloc(ctx->arglist[argpos], newlen);
if (!ctx->arglist[argpos])
pconf_fatal(ctx, "realloc arglist member failed");
/* remember the new size */
ctx->argsize[argpos] = newlen;
}
/* strncpy doesn't give us a trailing NULL, so prep the space */
memset(ctx->arglist[argpos], '\0', ctx->argsize[argpos]);
/* finally copy the new value into the provided space */
strncpy(ctx->arglist[argpos], ctx->wordbuf, wbuflen);
}
static void addchar(PCONF_CTX_t *ctx)
{
size_t wbuflen;
wbuflen = strlen(ctx->wordbuf);
if (ctx->wordlen_limit != 0) {
if (wbuflen >= ctx->wordlen_limit) {
/* limit reached: don't append any more */
return;
}
}
/* allow for the null */
if (wbuflen >= (ctx->wordbufsize - 1)) {
ctx->wordbufsize += 8;
ctx->wordbuf = realloc(ctx->wordbuf, ctx->wordbufsize);
if (!ctx->wordbuf)
pconf_fatal(ctx, "realloc wordbuf failed");
/* repoint as wordbuf may have moved */
ctx->wordptr = &ctx->wordbuf[wbuflen];
}
*ctx->wordptr++ = ctx->ch;
*ctx->wordptr = '\0';
}
static void endofword(PCONF_CTX_t *ctx)
{
if (ctx->arg_limit != 0) {
if (ctx->numargs >= ctx->arg_limit) {
/* don't accept this word - just drop it */
ctx->wordptr = ctx->wordbuf;
*ctx->wordptr = '\0';
return;
}
}
add_arg_word(ctx);
ctx->wordptr = ctx->wordbuf;
*ctx->wordptr = '\0';
}
/* look for the beginning of a word */
static int findwordstart(PCONF_CTX_t *ctx)
{
/* newline = the physical line is over, so the logical one is too */
if (ctx->ch == 10)
return STATE_ENDOFLINE;
/* the rest of the line is a comment */
if (ctx->ch == '#')
return STATE_FINDEOL;
/* space = not in a word yet, so loop back */
if (isspace(ctx->ch))
return STATE_FINDWORDSTART;
/* \ = literal = accept the next char blindly */
if (ctx->ch == '\\')
return STATE_COLLECTLITERAL;
/* " = begin word bounded by quotes */
if (ctx->ch == '"')
return STATE_QUOTECOLLECT;
/* at this point the word just started */
addchar(ctx);
return STATE_COLLECT;
}
/* eat characters until the end of the line is found */
static int findeol(PCONF_CTX_t *ctx)
{
/* newline = found it, so start a new line */
if (ctx->ch == 10)
return STATE_ENDOFLINE;
/* come back here */
return STATE_FINDEOL;
}
/* set up the error reporting details */
static void pconf_seterr(PCONF_CTX_t *ctx, const char *errmsg)
{
snprintf(ctx->errmsg, PCONF_ERR_LEN, "%s", errmsg);
ctx->error = 1;
}
/* quote characters inside a word bounded by "quotes" */
static int quotecollect(PCONF_CTX_t *ctx)
{
/* user is trying to break us */
if (ctx->ch == '#') {
pconf_seterr(ctx, "Unbalanced word due to unescaped # in quotes");
endofword(ctx);
/* this makes us drop all the way out of the caller */
return STATE_PARSEERR;
}
/* another " means we're done with this word */
if (ctx->ch == '"') {
endofword(ctx);
return STATE_FINDWORDSTART;
}
/* literal - special case since it needs to return here */
if (ctx->ch == '\\')
return STATE_QC_LITERAL;
/* otherwise save it and loop back */
addchar(ctx);
return STATE_QUOTECOLLECT;
}
/* take almost anything literally, but return to quotecollect */
static int qc_literal(PCONF_CTX_t *ctx)
{
/* continue onto the next line of the file */
if (ctx->ch == 10)
return STATE_QUOTECOLLECT;
addchar(ctx);
return STATE_QUOTECOLLECT;
}
/* collect characters inside a word */
static int collect(PCONF_CTX_t *ctx)
{
/* comment means the word is done, and skip to the end of the line */
if (ctx->ch == '#') {
endofword(ctx);
return STATE_FINDEOL;
}
/* newline means the word is done, and the line is done */
if (ctx->ch == 10) {
endofword(ctx);
return STATE_ENDOFLINE;
}
/* space means the word is done */
if (isspace(ctx->ch)) {
endofword(ctx);
return STATE_FINDWORDSTART;
}
/* \ = literal = accept the next char blindly */
if (ctx->ch == '\\')
return STATE_COLLECTLITERAL;
/* otherwise store it and come back for more */
addchar(ctx);
return STATE_COLLECT;
}
/* take almost anything literally */
static int collectliteral(PCONF_CTX_t *ctx)
{
/* continue to the next line */
if (ctx->ch == 10)
return STATE_COLLECT;
addchar(ctx);
return STATE_COLLECT;
}
/* clean up memory before going back to the user */
static void free_storage(PCONF_CTX_t *ctx)
{
unsigned int i;
free(ctx->wordbuf);
/* clear out the individual words first */
for (i = 0; i < ctx->maxargs; i++)
free(ctx->arglist[i]);
free(ctx->arglist);
free(ctx->argsize);
/* put things back to the initial state */
ctx->arglist = NULL;
ctx->argsize = NULL;
ctx->numargs = 0;
ctx->maxargs = 0;
}
int pconf_init(PCONF_CTX_t *ctx, void errhandler(const char *))
{
/* set up the ctx elements */
ctx->f = NULL;
ctx->state = STATE_FINDWORDSTART;
ctx->numargs = 0;
ctx->maxargs = 0;
ctx->arg_limit = PCONF_DEFAULT_ARG_LIMIT;
ctx->wordlen_limit = PCONF_DEFAULT_WORDLEN_LIMIT;
ctx->linenum = 0;
ctx->error = 0;
ctx->arglist = NULL;
ctx->argsize = NULL;
ctx->wordbufsize = 16;
ctx->wordbuf = calloc(1, ctx->wordbufsize);
if (!ctx->wordbuf)
pconf_fatal(ctx, "malloc wordbuf failed");
ctx->wordptr = ctx->wordbuf;
ctx->errhandler = errhandler;
ctx->magic = PCONF_CTX_t_MAGIC;
return 1;
}
static int check_magic(PCONF_CTX_t *ctx)
{
if (!ctx)
return 0;
if (ctx->magic != PCONF_CTX_t_MAGIC) {
snprintf(ctx->errmsg, PCONF_ERR_LEN, "Invalid ctx buffer");
return 0;
}
return 1;
}
int pconf_file_begin(PCONF_CTX_t *ctx, const char *fn)
{
if (!check_magic(ctx))
return 0;
ctx->f = fopen(fn, "r");
if (!ctx->f) {
snprintf(ctx->errmsg, PCONF_ERR_LEN, "Can't open %s: %s",
fn, strerror(errno));
return 0;
}
return 1; /* OK */
}
static void parse_char(PCONF_CTX_t *ctx)
{
switch(ctx->state) {
case STATE_FINDWORDSTART:
ctx->state = findwordstart(ctx);
break;
case STATE_FINDEOL:
ctx->state = findeol(ctx);
break;
case STATE_QUOTECOLLECT:
ctx->state = quotecollect(ctx);
break;
case STATE_QC_LITERAL:
ctx->state = qc_literal(ctx);
break;
case STATE_COLLECT:
ctx->state = collect(ctx);
break;
case STATE_COLLECTLITERAL:
ctx->state = collectliteral(ctx);
break;
} /* switch */
}
/* return 1 if an error occurred, but only do it once */
int pconf_parse_error(PCONF_CTX_t *ctx)
{
if (!check_magic(ctx))
return 0;
if (ctx->error == 1) {
ctx->error = 0;
return 1;
}
return 0;
}
/* clean up the ctx space */
void pconf_finish(PCONF_CTX_t *ctx)
{
if (!check_magic(ctx))
return;
if (ctx->f)
fclose(ctx->f);
free_storage(ctx);
ctx->magic = 0;
}
/* read from a file until a whole line is ready for use */
int pconf_file_next(PCONF_CTX_t *ctx)
{
if (!check_magic(ctx))
return 0;
ctx->linenum++;
/* start over for the new line */
ctx->numargs = 0;
ctx->state = STATE_FINDWORDSTART;
while ((ctx->ch = fgetc(ctx->f)) != EOF) {
parse_char(ctx);
if (ctx->state == STATE_PARSEERR)
return 1;
if (ctx->state == STATE_ENDOFLINE)
return 1;
}
/* deal with files that don't end in a newline */
if (ctx->numargs != 0) {
/* still building a word? */
if (ctx->wordptr != ctx->wordbuf)
endofword(ctx);
return 1;
}
/* finished with nothing left over */
return 0;
}
/* parse a provided line */
int pconf_line(PCONF_CTX_t *ctx, const char *line)
{
size_t i, linelen;
if (!check_magic(ctx))
return 0;
ctx->linenum++;
/* start over for the new line */
ctx->numargs = 0;
ctx->state = STATE_FINDWORDSTART;
linelen = strlen(line);
for (i = 0; i < linelen; i++) {
ctx->ch = line[i];
parse_char(ctx);
if (ctx->state == STATE_PARSEERR)
return 1;
if (ctx->state == STATE_ENDOFLINE)
return 1;
}
/* deal with any lingering characters */
/* still building a word? */
if (ctx->wordptr != ctx->wordbuf)
endofword(ctx); /* tie it off */
return 1;
}
#define PCONF_ESCAPE "#\\\""
char *pconf_encode(const char *src, char *dest, size_t destsize)
{
size_t i, srclen, destlen, maxlen;
if (destsize < 1)
return dest;
memset(dest, '\0', destsize);
/* always leave room for a final NULL */
maxlen = destsize - 1;
srclen = strlen(src);
destlen = 0;
for (i = 0; i < srclen; i++) {
if (strchr(PCONF_ESCAPE, src[i])) {
/* if they both won't fit, we're done */
if (destlen >= maxlen - 1)
return dest;
dest[destlen++] = '\\';
}
/* bail out when dest is full */
if (destlen >= maxlen)
return dest;
dest[destlen++] = src[i];
}
return dest;
}
/* parse input a character at a time */
int pconf_char(PCONF_CTX_t *ctx, char ch)
{
if (!check_magic(ctx))
return -1;
/* if the last call finished a line, clean stuff up for another */
if ((ctx->state == STATE_ENDOFLINE) || (ctx->state == STATE_PARSEERR)) {
ctx->numargs = 0;
ctx->state = STATE_FINDWORDSTART;
}
ctx->ch = ch;
parse_char(ctx);
if (ctx->state == STATE_ENDOFLINE)
return 1;
if (ctx->state == STATE_PARSEERR)
return -1;
return 0;
}

492
common/state.c Normal file
View file

@ -0,0 +1,492 @@
/* state.c - Network UPS Tools common state management functions
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
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 <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "common.h"
#include "state.h"
#include "parseconf.h"
static void val_escape(struct st_tree_t *node)
{
char etmp[ST_MAX_VALUE_LEN];
/* escape any tricky stuff like \ and " */
pconf_encode(node->raw, etmp, sizeof(etmp));
/* if nothing was escaped, we don't need to do anything else */
if (!strcmp(node->raw, etmp)) {
node->val = node->raw;
return;
}
/* if the escaped value grew, deal with it */
if (node->safesize < (strlen(etmp) + 1)) {
node->safesize = strlen(etmp) + 1;
node->safe = xrealloc(node->safe, node->safesize);
}
snprintf(node->safe, node->safesize, "%s", etmp);
node->val = node->safe;
}
static void st_tree_enum_free(struct enum_t *list)
{
if (!list) {
return;
}
st_tree_enum_free(list->next);
free(list->val);
free(list);
}
/* free all memory associated with a node */
static void st_tree_node_free(struct st_tree_t *node)
{
free(node->var);
free(node->raw);
free(node->safe);
/* never free node->val, since it's just a pointer to raw or safe */
/* blow away the list of enums */
st_tree_enum_free(node->enum_list);
/* now finally kill the node itself */
free(node);
}
/* add a subtree to another subtree */
static void st_tree_node_add(struct st_tree_t **nptr, struct st_tree_t *sptr)
{
if (!sptr) {
return;
}
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, sptr->var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, sptr->var) < 0) {
nptr = &node->right;
continue;
}
upsdebugx(1, "%s: duplicate value (shouldn't happen)", __func__);
return;
}
*nptr = sptr;
}
/* remove a variable from a tree */
int state_delinfo(struct st_tree_t **nptr, const char *var)
{
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
nptr = &node->right;
continue;
}
/* whatever is on the left, hang it off current right */
st_tree_node_add(&node->right, node->left);
/* now point the parent at the old right child */
*nptr = node->right;
st_tree_node_free(node);
return 1;
}
return 0; /* not found */
}
/* interface */
int state_setinfo(struct st_tree_t **nptr, const char *var, const char *val)
{
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
nptr = &node->right;
continue;
}
/* updating an existing entry */
if (!strcasecmp(node->raw, val)) {
return 0; /* no change */
}
/* changes should be ignored */
if (node->flags & ST_FLAG_IMMUTABLE) {
return 0; /* no change */
}
/* expand the buffer if the value grows */
if (node->rawsize < (strlen(val) + 1)) {
node->rawsize = strlen(val) + 1;
node->raw = xrealloc(node->raw, node->rawsize);
}
/* store the literal value for later comparisons */
snprintf(node->raw, node->rawsize, "%s", val);
val_escape(node);
return 1; /* changed */
}
*nptr = xcalloc(1, sizeof(**nptr));
(*nptr)->var = xstrdup(var);
(*nptr)->raw = xstrdup(val);
(*nptr)->rawsize = strlen(val) + 1;
val_escape(*nptr);
return 1; /* added */
}
static int st_tree_enum_add(struct enum_t **list, const char *enc)
{
struct enum_t *item;
while (*list) {
if (strcmp((*list)->val, enc)) {
list = &(*list)->next;
continue;
}
return 0; /* duplicate */
}
item = xcalloc(1, sizeof(*item));
item->val = xstrdup(enc);
item->next = *list;
/* now we're done creating it, add it to the list */
*list = item;
return 1; /* added */
}
int state_addenum(struct st_tree_t *root, const char *var, const char *val)
{
struct st_tree_t *sttmp;
char enc[ST_MAX_VALUE_LEN];
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_addenum: base variable (%s) "
"does not exist", var);
return 0; /* failed */
}
/* smooth over any oddities in the enum value */
pconf_encode(val, enc, sizeof(enc));
return st_tree_enum_add(&sttmp->enum_list, enc);
}
int state_setaux(struct st_tree_t *root, const char *var, const char *auxs)
{
struct st_tree_t *sttmp;
int aux;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_addenum: base variable (%s) "
"does not exist", var);
return -1; /* failed */
}
aux = strtol(auxs, (char **) NULL, 10);
/* silently ignore matches */
if (sttmp->aux == aux) {
return 0;
}
sttmp->aux = aux;
return 1;
}
const char *state_getinfo(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return NULL;
}
return sttmp->val;
}
int state_getflags(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return -1;
}
return sttmp->flags;
}
int state_getaux(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return -1;
}
return sttmp->aux;
}
const struct enum_t *state_getenumlist(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return NULL;
}
return sttmp->enum_list;
}
void state_setflags(struct st_tree_t *root, const char *var, int numflags, char **flag)
{
int i;
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_setflags: base variable (%s) "
"does not exist", var);
return;
}
sttmp->flags = 0;
for (i = 0; i < numflags; i++) {
if (!strcasecmp(flag[i], "RW")) {
sttmp->flags |= ST_FLAG_RW;
continue;
}
if (!strcasecmp(flag[i], "STRING")) {
sttmp->flags |= ST_FLAG_STRING;
continue;
}
upsdebugx(2, "Unrecognized flag [%s]", flag[i]);
}
}
int state_addcmd(struct cmdlist_t **list, const char *cmd)
{
struct cmdlist_t *item;
while (*list) {
if (strcasecmp((*list)->name, cmd) > 0) {
/* insertion point reached */
break;
}
if (strcasecmp((*list)->name, cmd) < 0) {
list = &(*list)->next;
continue;
}
return 0; /* duplicate */
}
item = xcalloc(1, sizeof(*item));
item->name = xstrdup(cmd);
item->next = *list;
/* now we're done creating it, insert it in the list */
*list = item;
return 1; /* added */
}
void state_infofree(struct st_tree_t *node)
{
if (!node) {
return;
}
state_infofree(node->left);
state_infofree(node->right);
st_tree_node_free(node);
}
void state_cmdfree(struct cmdlist_t *list)
{
if (!list) {
return;
}
state_cmdfree(list->next);
free(list->name);
free(list);
}
int state_delcmd(struct cmdlist_t **list, const char *cmd)
{
while (*list) {
struct cmdlist_t *item = *list;
if (strcasecmp(item->name, cmd) > 0) {
/* not found */
break;
}
if (strcasecmp(item->name, cmd) < 0) {
list = &item->next;
continue;
}
/* we found it! */
*list = item->next;
free(item->name);
free(item);
return 1; /* deleted */
}
return 0; /* not found */
}
static int st_tree_del_enum(struct enum_t **list, const char *val)
{
while (*list) {
struct enum_t *item = *list;
/* if this is not the right value, go on to the next */
if (strcasecmp(item->val, val)) {
list = &item->next;
continue;
}
/* we found it! */
*list = item->next;
free(item->val);
free(item);
return 1; /* deleted */
}
return 0; /* not found */
}
int state_delenum(struct st_tree_t *root, const char *var, const char *val)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return 0;
}
return st_tree_del_enum(&sttmp->enum_list, val);
}
struct st_tree_t *state_tree_find(struct st_tree_t *node, const char *var)
{
while (node) {
if (strcasecmp(node->var, var) > 0) {
node = node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
node = node->right;
continue;
}
break; /* found */
}
return node;
}

107
common/upsconf.c Normal file
View file

@ -0,0 +1,107 @@
/* upsconf.c - code for handling ups.conf ini-style parsing
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "upsconf.h"
#include "common.h"
#include "parseconf.h"
static char *ups_section;
/* handle arguments separated by parseconf */
static void conf_args(int numargs, char **arg)
{
char *ep;
if (numargs < 1)
return;
/* look for section headers - [upsname] */
if ((arg[0][0] == '[') && (arg[0][strlen(arg[0])-1] == ']')) {
free(ups_section);
arg[0][strlen(arg[0])-1] = '\0';
ups_section = xstrdup(&arg[0][1]);
return;
}
/* handle 'foo=bar' (compressed form) */
ep = strchr(arg[0], '=');
if (ep) {
*ep = '\0';
do_upsconf_args(ups_section, arg[0], ep+1);
return;
}
/* handle 'foo' (flag) */
if (numargs == 1) {
do_upsconf_args(ups_section, arg[0], NULL);
return;
}
if (numargs < 3)
return;
/* handle 'foo = bar' (split form) */
if (!strcmp(arg[1], "=")) {
do_upsconf_args(ups_section, arg[0], arg[2]);
return;
}
}
/* called for fatal errors in parseconf like malloc failures */
static void upsconf_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg);
}
/* open the ups.conf, parse it, and call back do_upsconf_args() */
void read_upsconf(void)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
ups_section = NULL;
snprintf(fn, sizeof(fn), "%s/ups.conf", confpath());
pconf_init(&ctx, upsconf_err);
if (!pconf_file_begin(&ctx, fn))
fatalx(EXIT_FAILURE, "Can't open %s: %s", fn, ctx.errmsg);
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
conf_args(ctx.numargs, ctx.arglist);
}
pconf_finish(&ctx);
free(ups_section);
}

142
compile Executable file
View file

@ -0,0 +1,142 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
scriptversion=2005-05-14.22
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.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, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# 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.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand `-c -o'.
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file `INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
esac
ofile=
cfile=
eat=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we strip `-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

17
conf/Makefile.am Normal file
View file

@ -0,0 +1,17 @@
# Network UPS Tools: conf
INSTALL_0600 = $(INSTALL) -m 0600
SECFILES = upsmon.conf.sample upsd.conf.sample upsd.users.sample
PUBFILES = nut.conf.sample ups.conf.sample
CGIPUB = hosts.conf.sample upsset.conf.sample upsstats.html.sample \
upsstats-single.html.sample
if WITH_CGI
CGI_INSTALL = $(CGIPUB)
else
CGI_INSTALL =
endif
dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL)
nodist_sysconf_DATA = upssched.conf.sample

497
conf/Makefile.in Normal file
View file

@ -0,0 +1,497 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# Network UPS Tools: conf
VPATH = @srcdir@
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 = conf
DIST_COMMON = $(am__dist_sysconf_DATA_DIST) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/upssched.conf.sample.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = upssched.conf.sample
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
am__dist_sysconf_DATA_DIST = upsmon.conf.sample upsd.conf.sample \
upsd.users.sample nut.conf.sample ups.conf.sample \
hosts.conf.sample upsset.conf.sample upsstats.html.sample \
upsstats-single.html.sample
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(sysconfdir)"
DATA = $(dist_sysconf_DATA) $(nodist_sysconf_DATA)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
INSTALL_0600 = $(INSTALL) -m 0600
SECFILES = upsmon.conf.sample upsd.conf.sample upsd.users.sample
PUBFILES = nut.conf.sample ups.conf.sample
CGIPUB = hosts.conf.sample upsset.conf.sample upsstats.html.sample \
upsstats-single.html.sample
@WITH_CGI_FALSE@CGI_INSTALL =
@WITH_CGI_TRUE@CGI_INSTALL = $(CGIPUB)
dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL)
nodist_sysconf_DATA = upssched.conf.sample
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 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);; \
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):
upssched.conf.sample: $(top_builddir)/config.status $(srcdir)/upssched.conf.sample.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-dist_sysconfDATA: $(dist_sysconf_DATA)
@$(NORMAL_INSTALL)
test -z "$(sysconfdir)" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)"
@list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \
done
uninstall-dist_sysconfDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(sysconfdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sysconfdir)" && rm -f $$files
install-nodist_sysconfDATA: $(nodist_sysconf_DATA)
@$(NORMAL_INSTALL)
test -z "$(sysconfdir)" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)"
@list='$(nodist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \
done
uninstall-nodist_sysconfDATA:
@$(NORMAL_UNINSTALL)
@list='$(nodist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(sysconfdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sysconfdir)" && rm -f $$files
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(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 $(DATA)
installdirs:
for dir in "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(sysconfdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
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:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
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-dist_sysconfDATA install-nodist_sysconfDATA
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: uninstall-dist_sysconfDATA uninstall-nodist_sysconfDATA
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dist_sysconfDATA \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-nodist_sysconfDATA 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 uninstall uninstall-am \
uninstall-dist_sysconfDATA uninstall-nodist_sysconfDATA
# 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:

29
conf/hosts.conf.sample Normal file
View file

@ -0,0 +1,29 @@
# Network UPS Tools: example hosts.conf
#
# This file is used to control the CGI programs. If you have not
# installed them, you may safely ignore or delete this file.
#
# -----------------------------------------------------------------------
#
# upsstats will use the list of MONITOR entries when displaying the
# default template (upsstats.html). The "FOREACHUPS" directive in the
# template will use this file to find systems running upsd.
#
# upsstats and upsimage also use this file to determine if a host may be
# monitored. This keeps evil people from using your system to annoy
# others with unintended queries.
#
# upsset presents a list of systems that may be viewed and controlled
# using this file.
#
# -----------------------------------------------------------------------
#
# Usage: list systems running upsd that you want to monitor
#
# MONITOR <system> "<host description>"
#
# Examples:
#
# MONITOR myups@localhost "Local UPS"
# MONITOR su2200@10.64.1.1 "Finance department"
# MONITOR matrix@shs-server.example.edu "Sierra High School data room #1"

28
conf/nut.conf.sample Normal file
View file

@ -0,0 +1,28 @@
# Network UPS Tools: example nut.conf
#
##############################################################################
# General section
##############################################################################
# The MODE determines which part of the NUT is to be started, and which
# configuration files must be modified.
#
# This file try to standardize the various files being found in the field, like
# /etc/default/nut on Debian based systems, /etc/sysconfig/ups on RedHat based
# systems, ... Distribution's init script should source this file to see which
# component(s) has to be started.
#
# The values of MODE can be:
# - none: NUT is not configured, or use the Integrated Power Management, or use
# some external system to startup NUT components. So nothing is to be started.
# - standalone: This mode address a local only configuration, with 1 UPS
# protecting the local system. This implies to start the 3 NUT layers (driver,
# upsd and upsmon) and the matching configuration files. This mode can also
# address UPS redundancy.
# - netserver: same as for the standalone configuration, but also need
# some more network access controls (firewall, tcp-wrappers) and possibly a
# specific LISTEN directive in upsd.conf.
# Since this MODE is opened to the network, a special care should be applied
# to security concerns.
# - netclient: this mode only requires upsmon.
MODE = none

104
conf/ups.conf.sample Normal file
View file

@ -0,0 +1,104 @@
# Network UPS Tools: example ups.conf
#
# --- SECURITY NOTE ---
#
# If you use snmp-ups and set a community string in here, you
# will have to secure this file to keep other users from obtaining
# that string. It needs to be readable by upsdrvctl and any drivers,
# and by upsd.
#
# ---
#
# This is where you configure all the UPSes that this system will be
# monitoring directly. These are usually attached to serial ports, but
# USB devices and SNMP devices are also supported.
#
# This file is used by upsdrvctl to start and stop your driver(s), and
# is also used by upsd to determine which drivers to monitor. The
# drivers themselves also read this file for configuration directives.
#
# The general form is:
#
# [upsname]
# driver = <drivername>
# port = <portname>
# < any other directives here >
#
# The section header ([upsname]) can be just about anything as long as
# it is a single word inside brackets. upsd uses this to uniquely
# identify a UPS on this system.
#
# 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:
#
# MONITOR snoopy@doghouse 1 upsmonuser mypassword master
#
# It might look like this if monitoring in slave mode:
#
# MONITOR snoopy@doghouse 1 upsmonuser mypassword slave
#
# Configuration directives
# ------------------------
#
# 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.
#
# 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.
#
# 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.
#
#
# Anything else is passed through to the hardware-specific part of
# the driver.
#
# Examples
# --------
#
# A simple example for a UPS called "powerpal" that uses the megatec
# driver on /dev/ttyS0 is:
#
# [powerpal]
# driver = megatec
# port = /dev/ttyS0
# desc = "Web server"
#
# If your UPS driver requires additional settings, you can specify them
# here. For example, if it supports a setting of "1234" for the
# variable "cable", it would look like this:
#
# [myups]
# driver = mydriver
# port = /dev/ttyS1
# cable = 1234
# desc = "Something descriptive"
#
# To find out if your driver supports any extra settings, start it with
# the -h option and/or read the driver's documentation.

41
conf/upsd.conf.sample Normal file
View file

@ -0,0 +1,41 @@
# Network UPS Tools: example upsd configuration file
#
# This file contains access control data, you should keep it secure.
#
# It should only be readable by the user that upsd becomes. See the FAQ.
# =======================================================================
# MAXAGE <seconds>
# MAXAGE 15
#
# This defaults to 15 seconds. After a UPS driver has stopped updating
# the data for this many seconds, upsd marks it stale and stops making
# that information available to clients. After all, the only thing worse
# than no data is bad data.
#
# You should only use this if your driver has difficulties keeping
# the data fresh within the normal 15 second interval. Watch the syslog
# for notifications from upsd about staleness.
# =======================================================================
# LISTEN <address> [<port>]
# LISTEN 127.0.0.1 3493
#
# This defaults to the localhost listening address and port 3493. You
# may specify each interface 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
# firewall, you may not want to listen to the external interface).
#
# This will only be read at startup of upsd. If you make changes here,
# you'll need to restart upsd, reload will have no effect.
# =======================================================================
# MAXCONN <connections>
#
# This defaults to maximum number allowed on your system. Each UPS, each
# LISTEN address and each client count as one connection. If the server
# runs out of connections, it will no longer accept new incoming client
# connections. Only set this if you know exactly what you're doing.

64
conf/upsd.users.sample Normal file
View file

@ -0,0 +1,64 @@
# Network UPS Tools: Example upsd.users
#
# This file sets the permissions for upsd - the UPS network daemon.
# Users are defined here, are given passwords, and their privileges are
# controlled here too. Since this file will contain passwords, keep it
# secure, with only enough permissions for upsd to read it.
# --------------------------------------------------------------------------
# Each user gets a section. To start a section, put the username in
# brackets on a line by itself. To set something for that user, specify
# it under that section heading. The username is case-sensitive, so
# admin and AdMiN are two different users.
#
# Possible settings:
#
# password: The user's password. This is case-sensitive.
#
# --------------------------------------------------------------------------
#
# actions: Let the user do certain things with upsd.
#
# Valid actions are:
#
# SET - change the value of certain variables in the UPS
# FSD - set the "forced shutdown" flag in the UPS
#
# --------------------------------------------------------------------------
#
# instcmds: Let the user initiate specific instant commands. Use "ALL"
# to grant all commands automatically. There are many possible
# commands, so use 'upscmd -l' to see what your hardware supports. Here
# are a few examples:
#
# test.panel.start - Start a front panel test
# test.battery.start - Start battery test
# test.battery.stop - Stop battery test
# calibrate.start - Start calibration
# calibrate.stop - Stop calibration
#
# --------------------------------------------------------------------------
#
# Example:
#
# [admin]
# password = mypass
# actions = SET
# instcmds = ALL
#
#
# --- Configuring for upsmon
#
# To add a user for your upsmon, use this example:
#
# [upsmon]
# password = pass
# upsmon master
# or
# upsmon slave
#
# The matching MONITOR line in your upsmon.conf would look like this:
#
# MONITOR myups@localhost 1 upsmon pass master (or slave)

299
conf/upsmon.conf.sample Normal file
View file

@ -0,0 +1,299 @@
# Network UPS Tools: example upsmon configuration
#
# This file contains passwords, so keep it secure.
# --------------------------------------------------------------------------
# RUN_AS_USER <userid>
#
# By default, upsmon splits into two processes. One stays as root and
# 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=...'.
#
# You can override it with '-u <user>' when starting upsmon, or just
# define it here for convenience.
#
# Note: if you plan to use the reload feature, this file (upsmon.conf)
# must be readable by this user! Since it contains passwords, DO NOT
# make it world-readable. Also, do not make it writable by the upsmon
# user, since it creates an opportunity for an attack by changing the
# SHUTDOWNCMD to something malicious.
#
# For best results, you should create a new normal user like "nutmon",
# and make it a member of a "nut" group or similar. Then specify it
# here and grant read access to the upsmon.conf for that group.
#
# This user should not have write access to upsmon.conf.
#
# RUN_AS_USER nutmon
# --------------------------------------------------------------------------
# MONITOR <system> <powervalue> <username> <password> ("master"|"slave")
#
# 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
# be in this section.
#
# You must have at least one of these declared.
#
# <system> is a UPS identifier in the form <upsname>@<hostname>[:<port>]
# like ups@localhost, su700@mybox, etc.
#
# Examples:
#
# - "su700@mybox" means a UPS called "su700" on a system called "mybox"
#
# - "fenton@bigbox:5678" is a UPS called "fenton" on a system called
# "bigbox" which runs upsd on port "5678".
#
# The UPS names like "su700" and "fenton" are set in your ups.conf
# in [brackets] which identify a section for a particular driver.
#
# If the ups.conf on host "doghouse" has a section called "snoopy", the
# 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.
#
# 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.
#
# <username> and <password> must match an entry in that system's
# upsd.users. If your username is "monmaster" and your password is
# "blah", the upsd.users would look like this:
#
# [monmaster]
# password = blah
# upsmon master (or slave)
#
# "master" means this system will shutdown last, allowing the slaves
# time to shutdown first.
#
# "slave" means this system shuts down immediately when power goes critical.
#
# 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)
# --------------------------------------------------------------------------
# MINSUPPLIES <num>
#
# Give the number of power supplies that must be receiving power to keep
# this system running. Most systems have one power supply, so you would
# 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,
# so you'd set that to 2. The idea is to keep the box running as long
# as possible, right?
#
# Obviously you have to put the redundant supplies on different UPS circuits
# for this to make sense! See big-servers.txt in the docs subdirectory
# for more information and ideas on how to use this feature.
MINSUPPLIES 1
# --------------------------------------------------------------------------
# SHUTDOWNCMD "<command>"
#
# 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.
SHUTDOWNCMD "/sbin/shutdown -h +0"
# --------------------------------------------------------------------------
# NOTIFYCMD <command>
#
# upsmon calls this to send messages when things happen
#
# This command is called with the full text of the message as one argument.
# The environment string NOTIFYTYPE will contain the type string of
# whatever caused this event to happen.
#
# 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 pager.txt in the docs directory.
#
# Example:
# NOTIFYCMD /usr/local/ups/bin/notifyme
# --------------------------------------------------------------------------
# POLLFREQ <n>
#
# Polling frequency for normal activities, measured in seconds.
#
# Adjust this to keep upsmon from flooding your network, but don't make
# it too high or it may miss certain short-lived power events.
POLLFREQ 5
# --------------------------------------------------------------------------
# POLLFREQALERT <n>
#
# Polling frequency in seconds while UPS on battery.
#
# You can make this number lower than POLLFREQ, which will make updates
# faster when any UPS is running on battery. This is a good way to tune
# network load if you have a lot of these things running.
#
# The default is 5 seconds for both this and POLLFREQ.
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.
#
# 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.
#
# This "wait for FSD" is done to avoid races where the status changes
# to critical and back between polls by the master.
HOSTSYNC 15
# --------------------------------------------------------------------------
# DEADTIME - Interval to wait before declaring a stale ups "dead"
#
# upsmon requires a UPS to provide status information every few seconds
# (see POLLFREQ and POLLFREQALERT) to keep things updated. If the status
# fetch fails, the UPS is marked stale. If it stays stale for more than
# DEADTIME seconds, the UPS is marked dead.
#
# A dead UPS that was last known to be on battery is assumed to have gone
# to a low battery condition. This may force a shutdown if it is providing
# a critical amount of power to your system.
#
# Note: DEADTIME should be a multiple of POLLFREQ and POLLFREQALERT.
# Otherwise you'll have "dead" UPSes simply because upsmon isn't polling
# them quickly enough. Rule of thumb: take the larger of the two
# POLLFREQ values, and multiply by 3.
DEADTIME 15
# --------------------------------------------------------------------------
# POWERDOWNFLAG - Flag file for forcing UPS shutdown on the master system
#
# upsmon will create a file with this name in master 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.
#
# See the shutdown.txt file in the docs subdirectory for more information.
POWERDOWNFLAG /etc/killpower
# --------------------------------------------------------------------------
# NOTIFYMSG - change messages sent by upsmon when certain events occur
#
# You can change the default messages to something else if you like.
#
# NOTIFYMSG <notify type> "message"
#
# NOTIFYMSG ONLINE "UPS %s on line power"
# NOTIFYMSG ONBATT "UPS %s on battery"
# NOTIFYMSG LOWBATT "UPS %s battery is low"
# NOTIFYMSG FSD "UPS %s: forced shutdown in progress"
# NOTIFYMSG COMMOK "Communications with UPS %s established"
# NOTIFYMSG COMMBAD "Communications with UPS %s lost"
# NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding"
# NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced"
# NOTIFYMSG NOCOMM "UPS %s is unavailable"
# NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible"
#
# Note that %s is replaced with the identifier of the UPS in question.
#
# Possible values for <notify type>:
#
# 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")
# COMMOK : Communications established with the UPS
# COMMBAD : Communications lost to the UPS
# SHUTDOWN : The system is being shutdown
# REPLBATT : The UPS battery is bad and needs to be replaced
# NOCOMM : A UPS is unavailable (can't be contacted for monitoring)
# NOPARENT : The process that shuts down the system has died (shutdown impossible)
# --------------------------------------------------------------------------
# NOTIFYFLAG - change behavior of upsmon when NOTIFY events occur
#
# By default, upsmon sends walls (global messages to all logged in users)
# and writes to the syslog when things happen. You can change this.
#
# NOTIFYFLAG <notify type> <flag>[+<flag>][+<flag>] ...
#
# NOTIFYFLAG ONLINE SYSLOG+WALL
# NOTIFYFLAG ONBATT SYSLOG+WALL
# NOTIFYFLAG LOWBATT SYSLOG+WALL
# NOTIFYFLAG FSD SYSLOG+WALL
# NOTIFYFLAG COMMOK SYSLOG+WALL
# NOTIFYFLAG COMMBAD SYSLOG+WALL
# NOTIFYFLAG SHUTDOWN SYSLOG+WALL
# NOTIFYFLAG REPLBATT SYSLOG+WALL
# NOTIFYFLAG NOCOMM SYSLOG+WALL
# NOTIFYFLAG NOPARENT SYSLOG+WALL
#
# Possible values for the flags:
#
# SYSLOG - Write the message in the syslog
# WALL - Write the message to all users on the system
# EXEC - Execute NOTIFYCMD (see above) with the message
# IGNORE - Don't do anything
#
# If you use IGNORE, don't use any other flags on the same line.
# --------------------------------------------------------------------------
# RBWARNTIME - replace battery warning time in seconds
#
# upsmon will normally warn you about a battery that needs to be replaced
# every 43200 seconds, which is 12 hours. It does this by triggering a
# NOTIFY_REPLBATT which is then handled by the usual notify structure
# you've defined above.
#
# If this number is not to your liking, override it here.
RBWARNTIME 43200
# --------------------------------------------------------------------------
# NOCOMMWARNTIME - no communications warning time in seconds
#
# upsmon will let you know through the usual notify system if it can't
# talk to any of the UPS entries that are defined in this file. It will
# trigger a NOTIFY_NOCOMM by default every 300 seconds unless you
# change the interval with this directive.
NOCOMMWARNTIME 300
# --------------------------------------------------------------------------
# FINALDELAY - last sleep interval before shutting down the system
#
# On a master, 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.
#
# 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.
FINALDELAY 5

View file

@ -0,0 +1,113 @@
# Network UPS Tools - upssched.conf sample file
#
# ============================================================================
#
# CMDSCRIPT <scriptname>
#
# This script gets called to invoke commands for timers that trigger.
# It is given a single argument - the <timername> in your
# AT ... START-TIMER defines.
#
# *** This must be defined *before* the first AT line. Otherwise the
# program will complain and exit without doing anything.
#
# A shell script with a big case..esac construct should work nicely for this.
# An example has been provided to help you get started.
CMDSCRIPT @BINDIR@/upssched-cmd
# ============================================================================
#
# PIPEFN <filename>
#
# This sets the file name of the FIFO that will pass communications between
# processes to start and stop timers. This should be set to some path where
# normal users can't create the file, due to the possibility of symlinking
# and other evil.
#
# Note: if you are running Solaris or similar, the permissions that
# upssched sets on this file *are not enough* to keep you safe. If
# your OS ignores the permissions on a FIFO, then you MUST put this in
# a protected directory!
#
# Note 2: by default, upsmon will run upssched as whatever user you have
# defined with RUN_AS_USER in upsmon.conf. Make sure that user can
# create files and write to files in the path you use for PIPEFN and
# LOCKFN.
#
# My recommendation: create a special directory for upssched, make it
# owned by your upsmon user, then use it for both.
#
# This is commented out by default to make you visit this file and think
# about how your system works before potentially opening a hole.
#
# PIPEFN @STATEPATH@/upssched/upssched.pipe
# ============================================================================
#
# LOCKFN <filename>
#
# REQUIRED. This was added after version 1.2.1.
#
# upssched needs to be able to create this filename in order to avoid
# a race condition when two events are dispatched from upsmon at nearly
# the same time. This file will only exist briefly. It must not be
# created by any other process.
#
# You should put this in the same directory as PIPEFN.
#
# LOCKFN @STATEPATH@/upssched/upssched.lock
# ============================================================================
#
# AT <notifytype> <upsname> <command>
#
# Define a handler for a specific event <notifytype> on UPS <upsname>.
#
# <upsname> can be the special value * to apply this handler to every
# possible value of <upsname>.
#
# Run the command <command> via your CMDSCRIPT when it happens.
#
# Note that any AT that matches both the <notifytype> and the <upsname>
# for the current event will be used.
# ============================================================================
#
# Possible AT commands
#
# - START-TIMER <timername> <interval>
#
# Start a timer called <timername> that will trigger after <interval>
# seconds, calling your CMDSCRIPT with <timername> as the first
# argument.
#
# Example:
# Start a timer that'll execute when any UPS (*) has been gone 10 seconds
#
# AT COMMBAD * START-TIMER upsgone 10
# -----------------------------------------------------------------------
#
# - CANCEL-TIMER <timername> [cmd]
#
# Cancel a running timer called <timername>, if possible. If the timer
# 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
#
# AT COMMOK myups@localhost CANCEL-TIMER upsgone
# -----------------------------------------------------------------------
#
# - EXECUTE <command>
#
# Immediately pass <command> as an argument to CMDSCRIPT.
#
# Example:
# If any UPS (*) reverts to utility power, then execute
# 'ups-back-on-line' via CMDSCRIPT.
#
# AT ONLINE * EXECUTE ups-back-on-line

36
conf/upsset.conf.sample Normal file
View file

@ -0,0 +1,36 @@
# Network UPS Tools - upsset.conf sample file
#
# This file is provided to ensure that you do not expose your upsd server
# to the world upon installing the CGI programs. Specifically, it keeps
# the upsset.cgi program from running until you have assured it that you
# have secured your web server's CGI directory.
#
# By default, your web server will probably let anyone access upsset.cgi
# once it is installed. This means that anyone could attempt to crack
# upsd logins since they would appear to be coming from your web server,
# rather than the outside world, slipping through any ACL/ACCESS definitions.
#
# For this reason, you *MUST* first secure your CGI programs before
# enabling upsset in this configuration file. If you can't do this in
# your web server, then you should *not* run this program.
#
# For Apache, the .htaccess file can be used in the directory with the
# programs. You'll need something like this:
#
# <Files upsset.cgi>
# deny from all
# allow from your.network.addresses
# </Files>
#
# You will probably have to set "AllowOverride Limit" for this directory in
# your server-level configuration file as well.
#
# If this doesn't make sense, then stop reading and leave this program alone.
#
# Assuming you have all this done (and it works), then you may uncomment
# the line below and start using upsset.cgi through your web browser.
#
###
### I_HAVE_SECURED_MY_CGI_DIRECTORY
###

View file

@ -0,0 +1,294 @@
<!-- upsstats template file -->
<!--
This is upsstats-single.html, a template for monitoring a single
host. This mode is selected by adding "host=<host>" to the
upsstats.cgi URL.
Such URLs are generated automatically when using the HOSTLINK
command.
See upsstats.html(5) for more information on template files.
-->
<!-- change this to TEMPF if you don't like Celsius. -->
@TEMPC@
@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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@REFRESH@
<title>@HOSTDESC@ : @VAR ups.model@ on @HOST@</title>
<!-- LINK REL="stylesheet" TYPE="text/css" HREF="http://localhost/nut/nut.css" / -->
</head>
<body BGCOLOR="#808080" TEXT="#00FC00" LINK="#0000EE" VLINK="#551A8B">
<table BORDER="1" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="10" BGCOLOR="#000000">
<tr>
<th COLSPAN="20">Network UPS Tools upsstats @VERSION@ - @HOSTDESC@ - @VAR ups.model@ on @HOST@</th>
</tr>
<tr>
<th>@DATE %a %b %d %X %Z %Y@</th>
@IFSUPP ambient.temperature@
<th>Ambient</th>
@ELSE@
@IFSUPP ambient.humidity@
<th>Ambient</th>
@ENDIF@
<th>Battery</th>
<th>Input</th>
<th>Output</th>
<th>Load</th>
</tr>
<tr>
<td BGCOLOR="#000000" VALIGN="TOP">
<table BORDER="0"> <!-- table 2 -->
<tr>
<th ALIGN="RIGHT">UPS Model:</th>
<td>@VAR ups.model@</td>
</tr>
<tr>
<th ALIGN="RIGHT">Status:</th>
<td>@STATUS@</td>
</tr>
@IFSUPP battery.runtime@
<tr>
<th ALIGN="RIGHT">Runtime:</th>
<td>@RUNTIME@</td>
</tr>
@ENDIF@
@IFSUPP ups.temperature@
<tr>
<th ALIGN="RIGHT">UPS temp:</th>
<td>@UPSTEMP@ @DEGREES@</td>
</tr>
@ENDIF@
@IFSUPP battery.voltage@
<tr>
<th ALIGN="RIGHT">Battery: </th>
<td>@VAR battery.voltage@ V@IFSUPP battery.current@, @VAR battery.current@ A</td>
@ENDIF@
<tr>
<th VALIGN="TOP" ALIGN="RIGHT">Input: </th>
<td>
@IFSUPP input.L2-L3.voltage@
@VAR input.L1-L2.voltage@ V<br>
@VAR input.L2-L3.voltage@ V<br>
@VAR input.L3-L1.voltage@ V<br>
</td>
</tr>
@ELSE@
@IFSUPP input.L2-N.voltage@
@VAR input.L1-N.voltage@ V<br>
@VAR input.L2-N.voltage@ V<br>
@VAR input.L3-N.voltage@ V<br>
</td>
</tr>
@ELSE@
@IFSUPP input.voltage@
@VAR input.voltage@ V<br>
</td>
</tr>
@ENDIF@
@IFSUPP input.L2.current@
<tr>
<th>
<td>
@VAR input.L1.current@ A<br>
@VAR input.L2.current@ A<br>
@VAR input.L3.current@ A<br>
</td>
</tr>
@ELSE@
@IFSUPP input.current@
<tr>
<th>
<td>
@VAR input.current@ A
</td>
</tr>
@ENDIF@
@IFSUPP input.frequency@
<tr>
<th>
<td>
@VAR input.frequency@ Hz
</td>
</tr>
@ENDIF@
<tr>
<th VALIGN="TOP" ALIGN="RIGHT">Output: </th>
<td>
@IFSUPP output.L2-L3.voltage@
@VAR output.L1-L2.voltage@ V<br>
@VAR output.L2-L3.voltage@ V<br>
@VAR output.L3-L1.voltage@ V<br>
</td>
</tr>
@ELSE@
@IFSUPP output.L2-N.voltage@
@VAR output.L1-N.voltage@ V<br>
@VAR output.L2-N.voltage@ V<br>
@VAR output.L3-N.voltage@ V<br>
</td>
</tr>
@ELSE@
@IFSUPP output.voltage@
@VAR output.voltage@ V
</td>
</tr>
@ENDIF@
@IFSUPP output.L2.current@
<tr>
<th>
<td>
@VAR output.L1.current@ A<br>
@VAR output.L2.current@ A<br>
@VAR output.L3.current@ A<br>
</td>
</tr>
@ELSE@
@IFSUPP output.current@
<tr>
<th>
<td>
@VAR output.current@ A
</td>
</tr>
@ENDIF@
@IFSUPP output.frequency@
<tr>
<th>
<td>
@VAR output.frequency@ Hz
</td>
</tr>
@ENDIF@
</table> <!-- table 2 -->
</td>
@IFSUPP ambient.temperature@
@IFSUPP ambient.humidity@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<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>
</tr></table>
</td>
@ELSE@
@IFSUPP ambient.temperature@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<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">
<table BORDER="0"><tr>
<td ALIGN="CENTER">Humidity<br>@IMG ambient.humidity@</td>
</tr></table>
</td>
@ENDIF@
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<table BORDER="0"><tr>
@IFSUPP battery.charge@
@IFSUPP battery.voltage@
<td ALIGN="CENTER">Charge<br>@IMG battery.charge width=90@</td>
<td ALIGN="CENTER">Voltage<br>@IMG battery.voltage width=90@</td>
@ELSE@
@IFSUPP battery.charge@
<td ALIGN="CENTER">Charge<br>@IMG battery.charge@</td>
@ELSE@
<td ALIGN="CENTER">Voltage<br>@IMG battery.voltage@</td>
@ENDIF@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<table BORDER="0"><tr>
@IFSUPP input.L2-L3.voltage@
<td ALIGN="CENTER">L1-L2<br>@IMG input.L1-L2.voltage width=68@</td>
<td ALIGN="CENTER">L2-L3<br>@IMG input.L2-L3.voltage width=68@</td>
<td ALIGN="CENTER">L3-L1<br>@IMG input.L3-L1.voltage width=68@</td>
@ELSE@
@IFSUPP input.L2-N.voltage@
<td ALIGN="CENTER">L1-N<br>@IMG input.L1-N.voltage width=68@</td>
<td ALIGN="CENTER">L2-N<br>@IMG input.L2-N.voltage width=68@</td>
<td ALIGN="CENTER">L3-N<br>@IMG input.L3-N.voltage width=68@</td>
@ELSE@
<td ALIGN="CENTER"><br>@IMG input.voltage@</td>
@ENDIF@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<table BORDER="0"><tr>
@IFSUPP output.L2-L3.voltage@
<td ALIGN="CENTER">L1-L2<br>@IMG output.L1-L2.voltage width=68@</td>
<td ALIGN="CENTER">L2-L3<br>@IMG output.L2-L3.voltage width=68@</td>
<td ALIGN="CENTER">L3-L1<br>@IMG output.L3-L1.voltage width=68@</td>
@ELSE@
@IFSUPP output.L2-N.voltage@
<td ALIGN="CENTER">L1-N<br>@IMG output.L1-N.voltage width=68@</td>
<td ALIGN="CENTER">L2-N<br>@IMG output.L2-N.voltage width=68@</td>
<td ALIGN="CENTER">L3-N<br>@IMG output.L3-N.voltage width=68@</td>
@ELSE@
<td ALIGN="CENTER"><br>@IMG output.voltage@</td>
@ENDIF@
</tr></table>
</td>
<td ALIGN="CENTER" VALIGN="TOP" BGCOLOR="#000000">
<table BORDER="0"><tr>
@IFSUPP output.L2.power.percent@
<td ALIGN="CENTER">L1<br>@IMG output.L1.power.percent width=68@</td>
<td ALIGN="CENTER">L2<br>@IMG output.L2.power.percent width=68@</td>
<td ALIGN="CENTER">L3<br>@IMG output.L3.power.percent width=68@</td>
@ELSE@
@IFSUPP output.L2.realpower.percent@
<td ALIGN="CENTER">L1<br>@IMG output.L1.realpower.percent width=68@</td>
<td ALIGN="CENTER">L2<br>@IMG output.L2.realpower.percent width=68@</td>
<td ALIGN="CENTER">L3<br>@IMG output.L3.realpower.percent width=68@</td>
@ELSE@
<td ALIGN="CENTER"><br>@IMG ups.load@</td>
@ENDIF@
</tr></table>
</td>
</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>
</body>
</html>

190
conf/upsstats.html.sample Normal file
View file

@ -0,0 +1,190 @@
<!-- upsstats template file -->
<!--
This (upsstats.html) is the default template file which is used
when upsstats.cgi is loaded with no arguments.
It usually contains a FOREACHUPS block to iterate through every
UPS in the hosts.conf.
See upsstats.html(5) for more information on template files.
-->
<!-- change this to TEMPF if you don't like Celsius. -->
@TEMPC@
@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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@REFRESH@
<title>
Network UPS Tools upsstats
@VERSION@
: UPS Status
</title>
<!-- link rel="stylesheet" type="text/css" href="nut.css" / -->
@REFRESH@
</head>
<body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000EE" VLINK="#551A8B">
<table BGCOLOR="#50A0A0" ALIGN="CENTER">
<tr><td>
<table CELLPADDING="5">
<tr>
<th COLSPAN="10" BGCOLOR="#60B0B0">
<font SIZE="+2">Network UPS Tools upsstats
@VERSION@
</font>
<br>
@DATE %a %b %d %X %Z %Y@
</th>
</tr>
<tr BGCOLOR="#60B0B0">
<th COLSPAN="1">System</th>
<th COLSPAN="1">Model</th>
<th COLSPAN="1">Status</th>
<th COLSPAN="1">Battery</th>
<th COLSPAN="1">Input (VAC)</th>
<th COLSPAN="1">Output (VAC)</th>
<th COLSPAN="1">Load (%)</th>
<th COLSPAN="1">UPS<br>Temp</th>
<th COLSPAN="1">Battery<br>Runtime</th>
<th COLSPAN="1">Data<br>Tree</th>
</tr>
@FOREACHUPS@
<tr ALIGN=CENTER>
<td BGCOLOR="#00FFFF">
@HOSTLINK@
</td>
<td BGCOLOR="#00FFFF">
@VAR ups.model@
</td>
<td BGCOLOR="@STATUSCOLOR@">
@STATUS@
</td>
<td BGCOLOR="#00FF00">
@IFSUPP battery.charge@
@VAR battery.charge@
%
@ENDIF@
</td>
@IFSUPP input.L2-L3.voltage@
@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">
@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">
@ELSE@
@IFBETWEEN input.transfer.low input.transfer.high input.voltage@
<td BGCOLOR="#00FF00">
@ELSE@
<td BGCOLOR="#FF0000">
@ENDIF@
@IFSUPP input.L2-L3.voltage@
@VAR input.L1-L2.voltage@
@VAR input.L2-L3.voltage@
@VAR input.L3-L1.voltage@
@ELSE@
@IFSUPP input.L2-N.voltage@
@VAR input.L1-N.voltage@
@VAR input.L2-N.voltage@
@VAR input.L3-N.voltage@
@ELSE@
@IFSUPP input.voltage@
@VAR input.voltage@
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
@IFSUPP output.L2-L3.voltage@
@VAR output.L1-L2.voltage@
@VAR output.L2-L3.voltage@
@VAR output.L3-L1.voltage@
@ELSE@
@IFSUPP output.L2-N.voltage@
@VAR output.L1-N.voltage@
@VAR output.L2-N.voltage@
@VAR output.L3-N.voltage@
@ELSE@
@IFSUPP output.voltage@
@VAR output.voltage@
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
@IFSUPP output.L2.power.percent@
@VAR output.L1.power.percent@
@VAR output.L2.power.percent@
@VAR output.L3.power.percent@
@ELSE@
@IFSUPP output.L2.realpower.percent@
@VAR output.L1.realpower.percent@
@VAR output.L2.realpower.percent@
@VAR output.L3.realpower.percent@
@ELSE@
@IFSUPP ups.load@
@VAR ups.load@
%
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
@IFSUPP ups.temperature@
@UPSTEMP@
@DEGREES@
@ELSE@
@IFSUPP battery.temperature@
@BATTTEMP@
@DEGREES@
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
@IFSUPP battery.runtime@
@RUNTIME@
@ENDIF@
</td>
<td BGCOLOR="#00FF00">
@TREELINK@
</td>
</tr>
@ENDFOR@
</table>
</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>
</small></div>
</body></html>

1561
config.guess vendored Executable file

File diff suppressed because it is too large Load diff

1686
config.sub vendored Executable file

File diff suppressed because it is too large Load diff

18664
configure vendored Executable file

File diff suppressed because it is too large Load diff

812
configure.in Normal file
View file

@ -0,0 +1,812 @@
dnl +------------------------------------------------------------------+
dnl | Network UPS Tools: configure.in |
dnl +------------------------------------------------------------------+
dnl NUT version number is defined here and *only* here (no more include/version)
AC_INIT(nut, 2.4.3)
AC_CONFIG_SRCDIR(server/upsd.c)
AC_CONFIG_MACRO_DIR([m4])
echo "Network UPS Tools version ${PACKAGE_VERSION}"
AC_CANONICAL_SYSTEM
NUT_CHECK_OS
AC_CONFIG_HEADER(include/config.h)
AC_PREFIX_DEFAULT(/usr/local/ups)
AM_INIT_AUTOMAKE
dnl Require Autoconf 2.60 or better and enable features of Posix that are extensions to C
AC_PREREQ([2.60])
AC_USE_SYSTEM_EXTENSIONS
dnl Use "./configure --enable-maintainer-mode" to keep Makefile.in and Makefile
dnl in sync after SVN updates.
AM_MAINTAINER_MODE
dnl # the following is commented out, because the UPS_VERSION macro now
dnl # resides in include/nut_version.h, which is generated by Makefile.am,
dnl # rather than in include/config.h, which is generated by configure. The
dnl # reason is that the SVN revision should be computed at compile time,
dnl # not configure time.
dnl AC_DEFINE_UNQUOTED(UPS_VERSION, "${PACKAGE_VERSION}", [NUT version])
dnl Fix this early so we can expand with eval later
test "${prefix}" = "NONE" && prefix="${ac_default_prefix}"
test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}'
CFLAGS=${CFLAGS-"-O"}
dnl NOTE: for definition of NUT_* autoconf macros, see m4/ directory
dnl and docs/macros.txt
dnl +------------------------------------------------------------------+
dnl | default values for things later on (can be overridden) |
STATEPATH="/var/state/ups"
cgiexecdir='${exec_prefix}/cgi-bin'
driverexecdir='${exec_prefix}/bin'
htmldir='${prefix}/html'
pkgconfigdir='${libdir}/pkgconfig'
hotplugdir='/etc/hotplug'
if test ! -d "${hotplugdir}"; then
hotplugdir=''
fi
udevdir='/lib/udev'
if test ! -d "${udevdir}"; then
udevdir='/etc/udev'
if test ! -d "${udevdir}"; then
udevdir=''
fi
fi
RUN_AS_USER="nobody"
RUN_AS_GROUP="nobody"
PIDPATH="/var/run"
dnl Define directory where LIBOBJS replacement functions are
AC_CONFIG_LIBOBJ_DIR([common])
dnl +-------------------------------------------------------------------
AC_PROG_CC
dnl Needed for per-target flags
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_EGREP
AC_PATH_PROG(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, :)
dnl Postpone call to AC_PROG_LIBTOOL to allow disabling static lib
AC_C_BIGENDIAN
AC_C_INLINE
AC_C_FLEXIBLE_ARRAY_MEMBER
AC_C_VARARRAYS
AC_CHECK_FUNCS(flock lockf fcvt fcvtl)
AC_CHECK_FUNCS(cfsetispeed tcsendbreak)
AC_CHECK_FUNCS(seteuid setsid getpassphrase)
AC_CHECK_FUNCS(on_exit strptime)
dnl the following may add stuff to LIBOBJS (is this still needed?)
AC_CHECK_FUNCS(vsnprintf snprintf, [], [
AC_LIBOBJ(snprintf)
AC_TYPE_LONG_DOUBLE
AC_TYPE_LONG_LONG_INT
])
AC_REPLACE_FUNCS(setenv inet_aton strerror atexit)
dnl
dnl Only use these when compiling with gcc
dnl
if ( test "${GCC}" = "yes" )
then
CFLAGS="${CFLAGS} -Wall -Wsign-compare"
fi
dnl optind handling:
dnl need to check if unistd.h is enough, else try getopt.h, else need decls
AC_CHECK_DECLS(optind, [], [
AC_CHECK_HEADERS(getopt.h, [
AC_DEFINE(NEED_GETOPT_H, 1, [Define if getopt.h is needed])
], [
AC_DEFINE(NEED_GETOPT_DECLS, 1, [Define to use explicit getopt declarations])
], [AC_INCLUDES_DEFAULT])
], [AC_INCLUDES_DEFAULT])
dnl FreeBSD serial locking compatibility - look for uu_lock in libutil.h
AC_CHECK_DECLS(uu_lock, [
AC_DEFINE(HAVE_UU_LOCK, 1, [Use uu_lock for locking (FreeBSD)])
SERLIBS="-lutil"
dnl put in some better defaults for FreeBSD
RUN_AS_USER="uucp"
], [
SERLIBS=""
], [
#include <sys/types.h>
#include <libutil.h>
])
AC_CHECK_DECLS(__func__, [], [
AC_CHECK_DECLS(__FUNCTION__, [
AC_DEFINE(__func__, __FUNCTION__, [Replace missing __func__ declaration])
], [
AC_DEFINE(__func__, __LINE__, [Replace missing __func__ declaration])
], [AC_INCLUDES_DEFAULT])
], [AC_INCLUDES_DEFAULT])
dnl Solaris compatibility - check for -lnsl and -lsocket
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(connect, socket)
AC_HEADER_TIME
AC_CHECK_HEADERS(sys/modem.h stdarg.h varargs.h sys/termios.h sys/time.h, [], [], [AC_INCLUDES_DEFAULT])
dnl ----------------------------------------------------------------------
dnl Check for types and define possible replacements
AX_CREATE_STDINT_H(include/nut_stdint.h)
NUT_TYPE_SOCKLEN_T
dnl ----------------------------------------------------------------------
dnl check for --with-all (or --without-all, or --with-all=auto) flag
AC_MSG_CHECKING(for --with-all)
AC_ARG_WITH(all,
AC_HELP_STRING([--with-all], [enable serial, usb, snmp, hal, cgi, dev, neon, powerman]),
[ if test -n "${withval}"; then
dnl Note: we allow "no" as a positive value, because
dnl this is what the user expects from --without-all
if test -z "${with_cgi}"; then with_cgi="${withval}"; fi
if test -z "${with_dev}"; then with_dev="${withval}"; fi
if test -z "${with_serial}"; then with_serial="${withval}"; fi
if test -z "${with_snmp}"; then with_snmp="${withval}"; fi
if test -z "${with_usb}"; then with_usb="${withval}"; fi
if test -z "${with_hal}"; then with_hal="${withval}"; fi
if test -z "${with_neon}"; then with_neon="${withval}"; fi
if test -z "${with_powerman}"; then with_powerman="${withval}"; fi
AC_MSG_RESULT("${withval}")
else
AC_MSG_RESULT(not given)
fi
], [ AC_MSG_RESULT(not given)
])
dnl ----------------------------------------------------------------------
dnl declare a number of --with-FEATURE options. Do this early, so that
dnl they are listed near the top by "./configure --help"
NUT_ARG_WITH([dev], [build and install the development files], [no])
NUT_ARG_WITH([serial], [build and install serial drivers], [yes])
NUT_ARG_WITH([usb], [build and install USB drivers], [auto])
NUT_CHECK_LIBUSB
NUT_ARG_WITH([hal], [build and install HAL support], [no])
NUT_CHECK_LIBHAL
NUT_ARG_WITH([snmp], [build and install SNMP drivers], [auto])
NUT_CHECK_LIBNETSNMP
NUT_ARG_WITH([neon], [build and install neon based XML/HTTP driver], [auto])
NUT_CHECK_LIBNEON
NUT_ARG_WITH([powerman], [build and install Powerman PDU client driver], [auto])
NUT_CHECK_LIBPOWERMAN
dnl ----------------------------------------------------------------------
dnl additional USB-related checks
dnl Solaris 10/11 USB handling (need librt and libusb runtime path)
case ${target_os} in
solaris2.1* )
echo Checking for Solaris 10 / 11 specific configuration for usb drivers
AC_SEARCH_LIBS(nanosleep, rt)
LIBUSB_LDFLAGS="-R/usr/sfw/lib ${LIBUSB_LDFLAGS}"
dnl FIXME: Sun's libusb doesn't support timeout (so blocks notification)
dnl and need to call libusb close upon reconnexion
AC_DEFINE(SUN_LIBUSB, 1, [Define to 1 for Sun version of the libusb.])
SUN_LIBUSB=1
;;
esac
dnl ----------------------------------------------------------------------
dnl Check for --with-ssl
NUT_ARG_WITH([ssl], [enable SSL development code], [auto])
dnl ${nut_with_ssl}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_ssl}" != "no"; then
dnl check for libssl compiler flags
NUT_CHECK_LIBSSL
fi
if test "${nut_with_ssl}" = "yes" -a "${nut_have_libssl}" != "yes"; then
AC_MSG_ERROR(["OpenSSL not found, required for SSL support"])
fi
if test "${nut_with_ssl}" != "no"; then
nut_with_ssl="${nut_have_libssl}"
fi
AM_CONDITIONAL(WITH_SSL, test "${nut_with_ssl}" = "yes")
NUT_REPORT_FEATURE([enable SSL development code], [${nut_with_ssl}])
dnl ----------------------------------------------------------------------
dnl Check for --with-wrap
NUT_ARG_WITH([wrap], [enable libwrap (tcp-wrappers) support], [auto])
dnl ${nut_with_wrap}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_wrap}" != "no"; then
dnl check for libwrap compiler flags
NUT_CHECK_LIBWRAP
fi
if test "${nut_with_wrap}" = "yes" -a "${nut_have_libwrap}" != "yes"; then
AC_MSG_ERROR(["libwrap not found"])
fi
if test "${nut_with_wrap}" != "no"; then
nut_with_wrap="${nut_have_libwrap}"
fi
AM_CONDITIONAL(WITH_WRAP, test "${nut_with_wrap}" = "yes")
NUT_REPORT_FEATURE([enable libwrap (tcp-wrappers) support], [${nut_with_wrap}])
dnl ----------------------------------------------------------------------
dnl check whether to compile IPv6 features
NUT_ARG_WITH([ipv6], [enable IPv6 support], [auto])
dnl ${nut_with_ipv6}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_ipv6}" != "no"; then
dnl check for IPv6 prerequisites
NUT_CHECK_IPV6
fi
if test "${nut_with_ipv6}" = "yes" -a "${nut_have_ipv6}" != "yes"; then
AC_MSG_ERROR(["Some feature required for IPv6 support is missing"])
fi
if test "${nut_with_ipv6}" != "no"; then
nut_with_ipv6="${nut_have_ipv6}"
fi
NUT_REPORT_FEATURE([enable IPv6 support], [${nut_with_ipv6}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-cgi
NUT_ARG_WITH([cgi], [build and install the CGI programs], [no])
dnl ${nut_with_cgi}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_cgi}" != "no"; then
dnl check for libgd compiler flags
NUT_CHECK_LIBGD
fi
if test "${nut_with_cgi}" = "yes" -a "${nut_have_libgd}" != "yes"; then
AC_MSG_ERROR([libgd not found, required for CGI build])
fi
if test "${nut_with_cgi}" != "no"; then
nut_with_cgi="${nut_have_libgd}"
fi
AM_CONDITIONAL(WITH_CGI, test "${nut_with_cgi}" = "yes")
NUT_REPORT_FEATURE([build CGI programs], [${nut_with_cgi}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-dev
dnl ${nut_with_dev}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_dev}" != "no"; then
nut_with_dev="yes"
else
AC_DISABLE_STATIC
fi
AM_CONDITIONAL(WITH_DEV, test "${nut_with_dev}" = "yes")
NUT_REPORT_FEATURE([build and install the development files], [${nut_with_dev}])
dnl We only init libtool there to allow AC_DISABLE_STATIC
AC_PROG_LIBTOOL
dnl ----------------------------------------------------------------------
dnl checks related to --with-serial
dnl ${nut_with_serial}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_serial}" != "no"; then
nut_with_serial="yes"
fi
AM_CONDITIONAL(WITH_SERIAL, test "${nut_with_serial}" = "yes")
NUT_REPORT_FEATURE([build serial drivers], [${nut_with_serial}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-snmp
dnl ${nut_with_snmp}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_snmp}" = "yes" -a "${nut_have_libnetsnmp}" != "yes"; then
AC_MSG_ERROR(["Net-SNMP libraries not found, required for SNMP drivers"])
fi
if test "${nut_with_snmp}" != "no"; then
nut_with_snmp="${nut_have_libnetsnmp}"
fi
AM_CONDITIONAL(WITH_SNMP, test "${nut_with_snmp}" = "yes")
NUT_REPORT_FEATURE([build SNMP drivers], [${nut_with_snmp}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-usb
dnl ${nut_with_usb}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_usb}" = "yes" -a "${nut_have_libusb}" != "yes"; then
AC_MSG_ERROR(["USB drivers requested, but libusb not found."])
fi
if test "${nut_with_usb}" != "no"; then
nut_with_usb="${nut_have_libusb}"
fi
AM_CONDITIONAL(WITH_USB, test "${nut_with_usb}" = "yes")
NUT_REPORT_FEATURE([build USB drivers], [${nut_with_usb}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-hal
dnl ${nut_with_hal}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_hal}" = "yes" -a "${nut_have_libhal}" != "yes"; then
AC_MSG_ERROR(["libhal not found, required for HAL support"])
fi
if test "${nut_with_hal}" = "yes" -a "${nut_have_libusb}" != "yes"; then
AC_MSG_ERROR(["libusb not found, required for HAL support"])
fi
if test "${nut_with_hal}" != "no"; then
if test "${nut_have_libhal}" = "yes" -a "${nut_have_libusb}" = "yes"; then
nut_with_hal="yes"
else
nut_with_hal="no"
fi
fi
AM_CONDITIONAL(WITH_HAL, test "${nut_with_hal}" = "yes")
NUT_REPORT_FEATURE([enable HAL support], [${nut_with_hal}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-neon
dnl ${nut_with_neon}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_neon}" = "yes" -a "${nut_have_neon}" != "yes"; then
AC_MSG_ERROR(["neon libraries not found, required for neon based XML/HTTP driver"])
fi
if test "${nut_with_neon}" != "no"; then
nut_with_neon="${nut_have_neon}"
fi
AM_CONDITIONAL(WITH_NEONXML, test "${nut_with_neon}" = "yes")
NUT_REPORT_FEATURE([build neon based XML driver], [${nut_with_neon}])
dnl ----------------------------------------------------------------------
dnl checks related to --with-powerman
dnl ${nut_with_powerman}: any value except "yes" or "no" is treated as "auto".
if test "${nut_with_powerman}" = "yes" -a "${nut_have_libpowerman}" != "yes"; then
AC_MSG_ERROR(["Powerman client libraries not found, required for Powerman PDU client driver"])
fi
if test "${nut_with_powerman}" != "no"; then
nut_with_powerman="${nut_have_libpowerman}"
fi
AM_CONDITIONAL(WITH_LIBPOWERMAN, test "${nut_with_powerman}" = "yes")
NUT_REPORT_FEATURE([build Powerman PDU client driver], [${nut_with_powerman}])
dnl ----------------------------------------------------------------------
AC_MSG_CHECKING(state path)
AC_ARG_WITH(statepath,
AC_HELP_STRING([--with-statepath=PATH], [path for ups state files (/var/state/ups)]),
[ case "${withval}" in
yes|no)
;;
*)
STATEPATH="${withval}"
;;
esac],
)
AC_DEFINE_UNQUOTED(STATEPATH, "${STATEPATH}",
[Path for UPS driver state files])
AC_MSG_RESULT(${STATEPATH})
dnl ---------------------------------------------------------------------
dnl The 'alt pid path' is used by the drivers (via main.c) and upsd, since
dnl ideally they do not run as root and won't be able to write to the usual
dnl /var/run path. This defaults to the STATEPATH since they should be
dnl able to write there.
dnl
AC_MSG_CHECKING(alt pid path)
AC_ARG_WITH(altpidpath,
AC_HELP_STRING([--with-altpidpath=PATH], [path for driver/upsd .pid files (<statepath>)]),
[ case "${withval}" in
yes|no)
ALTPIDPATH="${STATEPATH}"
;;
*)
ALTPIDPATH="${withval}"
;;
esac],
ALTPIDPATH="${STATEPATH}"
)
AC_DEFINE_UNQUOTED(ALTPIDPATH, "${ALTPIDPATH}",
[Path for pid files of drivers and upsd (usually STATEPATH)])
AC_MSG_RESULT(${ALTPIDPATH})
AC_MSG_CHECKING(driver path)
AC_ARG_WITH(drvpath,
AC_HELP_STRING([--with-drvpath=PATH], [where to install ups drivers (EPREFIX/bin)]),
[ case "${withval}" in
yes|no)
;;
*)
driverexecdir="${withval}"
;;
esac],
)
conftemp="${driverexecdir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
AC_DEFINE_UNQUOTED(DRVPATH, "${conftemp}", [Default path for UPS drivers])
AC_MSG_RESULT(${driverexecdir})
AC_MSG_CHECKING(cgi path)
AC_ARG_WITH(cgipath,
AC_HELP_STRING([--with-cgipath=PATH], [where to install CGI programs (EPREFIX/cgi-bin)]),
[ case "${withval}" in
yes|no)
;;
*)
cgiexecdir="${withval}"
;;
esac],
)
conftemp="${cgiexecdir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
AC_DEFINE_UNQUOTED(CGIPATH, "${conftemp}", [Default path for CGI programs])
AC_MSG_RESULT(${cgiexecdir})
AC_MSG_CHECKING(html path)
AC_ARG_WITH(htmlpath,
AC_HELP_STRING([--with-htmlpath=PATH], [where to install HTML files (PREFIX/html)]),
[ case "${withval}" in
yes|no)
;;
*)
htmldir="${withval}"
;;
esac],
)
conftemp="${htmldir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
AC_DEFINE_UNQUOTED(HTMLPATH, "${conftemp}", [Default path for HTML files])
AC_MSG_RESULT(${htmldir})
AC_MSG_CHECKING(pidpath)
AC_ARG_WITH(pidpath,
AC_HELP_STRING([--with-pidpath=PATH], [path for .pid files (/var/run)]),
[ case "${withval}" in
yes|no)
;;
*)
PIDPATH="${withval}"
;;
esac],
)
AC_DEFINE_UNQUOTED(PIDPATH, "${PIDPATH}", [Path where the pid files should go])
AC_MSG_RESULT(${PIDPATH})
AC_MSG_CHECKING(network port number)
AC_ARG_WITH(port,
AC_HELP_STRING([--with-port=PORT], [port for network communications (3493)]),
[ case "${withval}" in
yes|no)
PORT="3493"
;;
*)
PORT="${withval}"
;;
esac],
PORT="3493"
)
AC_DEFINE_UNQUOTED(PORT, ${PORT}, [Port for network communications])
AC_MSG_RESULT(${PORT})
nut_user_given=
AC_MSG_CHECKING(user to run as)
AC_ARG_WITH(user,
AC_HELP_STRING([--with-user=username], [user for programs started as root (nobody)]),
[ case "${withval}" in
yes|no)
;;
*)
RUN_AS_USER="${withval}"
nut_user_given=yes
;;
esac],
)
AC_DEFINE_UNQUOTED(RUN_AS_USER, "${RUN_AS_USER}",
[User to switch to if started as root])
AC_MSG_RESULT(${RUN_AS_USER})
nut_group_given=
AC_MSG_CHECKING(group membership of user to run as)
AC_ARG_WITH(group,
AC_HELP_STRING([--with-group=groupname], [group membership of user for programs started as root (nogroup)]),
[ case "${withval}" in
yes|no)
;;
*)
RUN_AS_GROUP="${withval}"
nut_group_given=yes
;;
esac],
)
AC_DEFINE_UNQUOTED(RUN_AS_GROUP, "${RUN_AS_GROUP}",
[Group membership of user to switch to if started as root])
AC_MSG_RESULT(${RUN_AS_GROUP})
dnl check that --with-user is given iff --with-group is given.
if test -n "$nut_user_given" -a -z "$nut_group_given"; then
AC_MSG_ERROR(["If you specify --with-user, you also must specify --with-group"])
elif test -z "$nut_user_given" -a -n "$nut_group_given"; then
AC_MSG_ERROR(["If you specify --with-group, you also must specify --with-user"])
fi
AC_MSG_CHECKING(facility for syslog)
AC_ARG_WITH(logfacility,
AC_HELP_STRING([--with-logfacility=FACILITY], [facility for log messages (LOG_DAEMON)]),
[ case "${withval}" in
yes|no)
LOGFACILITY="LOG_DAEMON"
;;
*)
LOGFACILITY="${withval}"
;;
esac],
LOGFACILITY="LOG_DAEMON"
)
AC_DEFINE_UNQUOTED(LOG_FACILITY, ${LOGFACILITY},
[Desired syslog facility - see syslog(3)])
AC_MSG_RESULT(${LOGFACILITY})
AC_MSG_CHECKING(which drivers to build)
AC_ARG_WITH(drivers,
AC_HELP_STRING([[[[--with-drivers=driver@<:@,driver...@:>@]]]], [Only use specific drivers (all)]),
[ case "${withval}" in
yes | no)
dnl ignore calls without any arguments
DRIVER_BUILD_LIST="all"
AC_MSG_RESULT(all available)
;;
*)
DRIVER_BUILD_LIST=`echo ${withval} | sed "s/,/ /g"`
AC_MSG_RESULT(${DRIVER_BUILD_LIST})
;;
esac
],
[
DRIVER_BUILD_LIST="all"
AC_MSG_RESULT(all available)
]
)
AM_CONDITIONAL(SOME_DRIVERS, test "${DRIVER_BUILD_LIST}" != "all")
if test "${DRIVER_BUILD_LIST}" != "all"; then
NUT_REPORT([only build specific drivers], [${DRIVER_BUILD_LIST}])
fi
AC_MSG_CHECKING(which driver man pages to install)
if test "${DRIVER_BUILD_LIST}" = "all"; then
DRIVER_MAN_LIST=all
AC_MSG_RESULT(all available)
else
DRIVER_MAN_LIST=""
for i in ${DRIVER_BUILD_LIST}; do
if test -f ${srcdir}/man/$i.8; then
DRIVER_MAN_LIST="${DRIVER_MAN_LIST} $i.8"
fi
done
AC_MSG_RESULT(${DRIVER_MAN_LIST})
fi
AC_MSG_CHECKING(whether to strip debug symbols)
AC_ARG_ENABLE(strip,
[ --enable-strip Strip debugging symbols from binaries [no]],
[
case "${withval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
CFLAGS="${CFLAGS} -s"
;;
esac
],
[ AC_MSG_RESULT(no)
])
AC_MSG_CHECKING(whether to install pkg-config *.pc files)
AC_ARG_WITH(pkgconfig-dir,
AC_HELP_STRING([--with-pkgconfig-dir=PATH], [where to install pkg-config *.pc files (EPREFIX/lib/pkgconfig)]),
[
case "${withval}" in
yes|auto)
;;
no)
pkgconfigdir=""
;;
*)
pkgconfigdir="${withval}"
;;
esac
],
)
echo ${pkgconfigdir}
if test -n "${pkgconfigdir}"; then
AC_MSG_RESULT(using ${pkgconfigdir})
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(WITH_PKG_CONFIG, test -n "${pkgconfigdir}")
AC_MSG_CHECKING(whether to install hotplug rules)
AC_ARG_WITH(hotplug-dir,
AC_HELP_STRING([--with-hotplug-dir=PATH], [where to install hotplug rules (/etc/hotplug)]),
[
case "${withval}" in
yes)
if test -z "${hotplugdir}"; then
AC_MSG_RESULT(no)
AC_MSG_ERROR(["hotplug directory requested but not found])
fi
;;
auto)
;;
no)
hotplugdir=""
;;
*)
hotplugdir="${withval}"
;;
esac
],
)
if test -n "${hotplugdir}"; then
AC_MSG_RESULT(using ${hotplugdir})
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(WITH_HOTPLUG, test -n "${hotplugdir}")
AC_MSG_CHECKING(whether to install udev rules)
AC_ARG_WITH(udev-dir,
AC_HELP_STRING([--with-udev-dir=PATH], [where to install udev rules (/lib/udev or /etc/udev)]),
[
case "${withval}" in
yes)
if test -z "${udevdir}"; then
AC_MSG_RESULT(no)
AC_MSG_ERROR(["udev directory requested but not found])
fi
;;
auto)
;;
no)
udevdir=""
;;
*)
udevdir="${withval}"
;;
esac
],
)
if test -n "${udevdir}"; then
AC_MSG_RESULT(using ${udevdir})
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(WITH_UDEV, test -n "${udevdir}")
dnl expand ${sysconfdir} and write it out
conftemp="${sysconfdir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
CONFPATH=${conftemp}
AC_DEFINE_UNQUOTED(CONFPATH, "${conftemp}",
[Default path for configuration files])
dnl same for datadir
conftemp="${datadir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
AC_DEFINE_UNQUOTED(DATADIR, "${conftemp}",
[Default path for data files])
dnl same for bindir
conftemp="${bindir}"
eval conftemp=\"${conftemp}\"
eval conftemp=\"${conftemp}\"
AC_DEFINE_UNQUOTED(BINDIR, "${conftemp}",
[Default path for user executables])
AC_SUBST(OS_NAME)
AC_SUBST(LIBSSL_CFLAGS)
AC_SUBST(LIBSSL_LDFLAGS)
AC_SUBST(LIBGD_CFLAGS)
AC_SUBST(LIBGD_LDFLAGS)
AC_SUBST(LIBNETSNMP_CFLAGS)
AC_SUBST(LIBNETSNMP_LDFLAGS)
AC_SUBST(LIBUSB_CFLAGS)
AC_SUBST(LIBUSB_LDFLAGS)
AC_SUBST(LIBNEON_CFLAGS)
AC_SUBST(LIBNEON_LDFLAGS)
AC_SUBST(LIBPOWERMAN_CFLAGS)
AC_SUBST(LIBPOWERMAN_LDFLAGS)
AC_SUBST(LIBWRAP_CFLAGS)
AC_SUBST(LIBWRAP_LDFLAGS)
AC_SUBST(HAL_USER)
AC_SUBST(HAL_DEVICE_MATCH_KEY)
AC_SUBST(HAL_FDI_PATH)
AC_SUBST(HAL_CALLOUTS_PATH)
AC_SUBST(HAVE_GLIB_2_14)
AC_SUBST(LIBHAL_CFLAGS)
AC_SUBST(LIBHAL_LDFLAGS)
AC_SUBST(DRIVER_BUILD_LIST)
AC_SUBST(DRIVER_MAN_LIST)
AC_SUBST(DRIVER_INSTALL_TARGET)
AC_SUBST(NETLIBS)
AC_SUBST(SERLIBS)
AC_SUBST(STATEPATH)
AC_SUBST(CONFPATH)
AC_SUBST(BINDIR)
AC_SUBST(RUN_AS_USER)
AC_SUBST(RUN_AS_GROUP)
AC_SUBST(SUN_LIBUSB)
AC_SUBST(WORDS_BIGENDIAN)
AC_SUBST(cgiexecdir)
AC_SUBST(driverexecdir)
AC_SUBST(htmldir)
AC_SUBST(pkgconfigdir)
AC_SUBST(hotplugdir)
AC_SUBST(udevdir)
AC_OUTPUT([
clients/Makefile
common/Makefile
conf/Makefile
conf/upssched.conf.sample
data/html/header.html
data/html/Makefile
data/Makefile
docs/Makefile
drivers/Makefile
include/Makefile
lib/libupsclient-config
lib/libupsclient.pc
lib/Makefile
man/Makefile
scripts/hal/Makefile
scripts/hal/ups-nut-device.fdi
scripts/hotplug/Makefile
scripts/hotplug/libhidups
scripts/python/Makefile
scripts/udev/Makefile
scripts/udev/nut-usbups.rules
scripts/Makefile
server/Makefile
tools/Makefile
Makefile
])
NUT_PRINT_FEATURE_REPORT

8
data/Makefile.am Normal file
View file

@ -0,0 +1,8 @@
# Network UPS Tools: data
SUBDIRS = html
dist_data_DATA = cmdvartab driver.list
EXTRA_DIST = evolution500.dev
DATA_FILES = cmdvartab driver.list

666
data/Makefile.in Normal file
View file

@ -0,0 +1,666 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# Network UPS Tools: data
VPATH = @srcdir@
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 = data
DIST_COMMON = $(dist_data_DATA) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
install-html-recursive install-info-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(datadir)"
DATA = $(dist_data_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
distdir
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
SUBDIRS = html
dist_data_DATA = cmdvartab driver.list
EXTRA_DIST = evolution500.dev
DATA_FILES = cmdvartab driver.list
all: all-recursive
.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 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);; \
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
install-dist_dataDATA: $(dist_data_DATA)
@$(NORMAL_INSTALL)
test -z "$(datadir)" || $(MKDIR_P) "$(DESTDIR)$(datadir)"
@list='$(dist_data_DATA)'; test -n "$(datadir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(datadir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(datadir)" || exit $$?; \
done
uninstall-dist_dataDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_data_DATA)'; test -n "$(datadir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(datadir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(datadir)" && rm -f $$files
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(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
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile $(DATA)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(datadir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am: install-dist_dataDATA
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-dist_dataDATA
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am check check-am clean clean-generic clean-libtool \
ctags ctags-recursive 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-dist_dataDATA 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-recursive uninstall uninstall-am \
uninstall-dist_dataDATA
# 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:

189
data/cmdvartab Normal file
View file

@ -0,0 +1,189 @@
# Network UPS Tools: variable and command descriptions
#
# This file is optional. You may delete it to save resources, but
# clients will receive "Unavailable" for any description requests.
#
# *** NOTE *** : When updating this file, also update docs/new-names.txt
VARDESC ups.alarm "UPS alarms"
VARDESC ups.status "UPS status"
VARDESC ups.time "Internal UPS clock time"
VARDESC ups.date "Internal UPS clock date"
VARDESC ups.model "UPS model"
VARDESC ups.mfr "UPS manufacturer"
VARDESC ups.mfr.date "UPS manufacturing date"
VARDESC ups.serial "UPS serial number"
VARDESC ups.vendorid "Vendor ID for USB devices"
VARDESC ups.productid "Product ID for USB devices"
VARDESC ups.firmware "UPS firmware"
VARDESC ups.firmware.aux "Auxiliary device firmware"
VARDESC ups.temperature "UPS temperature (degrees C)"
VARDESC ups.load "Load on UPS (percent of full)"
VARDESC ups.load.high "Load when UPS switches to overload condition (percent)"
VARDESC ups.id "UPS system identifier"
VARDESC ups.delay.start "Interval to wait before (re)starting the load (seconds)"
VARDESC ups.delay.reboot "Interval to wait before rebooting the UPS (seconds)"
VARDESC ups.delay.shutdown "Interval to wait after shutdown with delay command (seconds)"
VARDESC ups.timer.start "Time before the load will be started (seconds)"
VARDESC ups.timer.reboot "Time before the load will be rebooted (seconds)"
VARDESC ups.timer.shutdown "Time before the load will be shutdown (seconds)"
VARDESC ups.test.interval "Interval between self tests (seconds)"
VARDESC ups.test.result "Results of last self test"
VARDESC ups.display.language "Language to use on front panel"
VARDESC ups.contacts "UPS external contact sensors"
VARDESC ups.power "Current value of apparent power (VA)"
VARDESC ups.power.nominal "UPS power rating (VA)"
VARDESC ups.realpower "Current value of real power (W)"
VARDESC ups.realpower.nominal "UPS real power rating (W)"
VARDESC ups.beeper.status "UPS beeper status"
VARDESC ups.type "UPS type"
VARDESC ups.start.auto "UPS starts when mains is (re)applied"
VARDESC ups.start.battery "Allow to start UPS from battery"
VARDESC ups.start.reboot "UPS reboots when power returns during shutdown delay"
VARDESC input.voltage "Input voltage (V)"
VARDESC input.voltage.extended "Extended input voltage range"
VARDESC input.voltage.maximum "Maximum incoming voltage seen (V)"
VARDESC input.voltage.minimum "Minimum incoming voltage seen (V)"
VARDESC input.voltage.nominal "Nominal input voltage (V)"
VARDESC input.transfer.reason "Reason for last transfer to battery"
VARDESC input.transfer.low "Low voltage transfer point (V)"
VARDESC input.transfer.high "High voltage transfer point (V)"
VARDESC input.transfer.low.min "smallest settable low voltage transfer point (V)"
VARDESC input.transfer.low.max "greatest settable low voltage transfer point (V)"
VARDESC input.transfer.high.min "smallest settable high voltage transfer point (V)"
VARDESC input.transfer.high.max "greatest settable high voltage transfer point (V)"
VARDESC input.sensitivity "Input power sensitivity"
VARDESC input.quality "Input power quality"
VARDESC input.current "Input current (A)"
VARDESC input.current.nominal "Nominal input current (A)"
VARDESC input.frequency "Input line frequency (Hz)"
VARDESC input.frequency.extended "Extended input frequency range"
VARDESC input.frequency.nominal "Nominal input line frequency (Hz)"
VARDESC input.frequency.low "Minimum input line frequency (Hz)"
VARDESC input.frequency.high "Maximum input line frequency (Hz)"
VARDESC input.transfer.boost.low "Low voltage boosting transfer point (V)"
VARDESC input.transfer.boost.high "High voltage boosting transfer point (V)"
VARDESC input.transfer.trim.low "Low voltage trimming transfer point (V)"
VARDESC input.transfer.trim.high "High voltage trimming transfer point (V)"
VARDESC output.voltage "Output voltage (V)"
VARDESC output.voltage.nominal "Nominal output voltage (V)"
VARDESC output.frequency "Output frequency (Hz)"
VARDESC output.frequency.nominal "Nominal output frequency (Hz)"
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.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)"
VARDESC battery.voltage "Battery voltage (V)"
VARDESC battery.current "Battery current (A)"
VARDESC battery.capacity "Battery capacity (Ah)"
VARDESC battery.temperature "Battery temperature (degrees C)"
VARDESC battery.voltage.nominal "Nominal battery voltage (V)"
VARDESC battery.runtime "Battery runtime (seconds)"
VARDESC battery.runtime.low "Remaining battery runtime when UPS switches to LB (seconds)"
VARDESC battery.alarm.threshold "Battery alarm threshold"
VARDESC battery.date "Battery change date"
VARDESC battery.mfr.date "Battery manufacturing date"
VARDESC battery.packs "Number of battery packs"
VARDESC battery.packs.bad "Number of bad battery packs"
VARDESC battery.type "Battery chemistry"
VARDESC battery.protection "Prevent deep discharge of battery"
VARDESC battery.energysave "Switch off when running on battery and no/low load"
VARDESC ambient.temperature "Ambient temperature (degrees C)"
VARDESC ambient.temperature.alarm "Ambient temperature alarm is active"
VARDESC ambient.temperature.alarm.maximum "Maximum allowed ambient temperature"
VARDESC ambient.temperature.alarm.minimum "Minimum allowed ambient temperature"
VARDESC ambient.temperature.alarm.enable "Enable ambient temperature alarm"
VARDESC ambient.humidity "Ambient humidity"
VARDESC ambient.humidity.alarm "Ambient humidity alarm is active"
VARDESC ambient.humidity.alarm.maximum "Maximum allowed ambient humidity"
VARDESC ambient.humidity.alarm.minimum "Minimum allowed ambient humidity"
VARDESC ambient.humidity.alarm.enable "Enable ambient humidity alarm"
# FIXME: the outlet collection is indexed - solve with regexs?
#
# VARDESC outlet.[[:digit:]]+.id "Outlet system identifier (<index>)"
VARDESC outlet.id "Outlet system identifier"
VARDESC outlet.desc "Outlet description"
VARDESC outlet.switch "Outlet switch control"
VARDESC outlet.status "Outlet switch status"
VARDESC outlet.switchable "Outlet switch ability"
VARDESC outlet.autoswitch.charge.low "Remaining battery level to power off this outlet (percent)"
VARDESC outlet.delay.shutdown "Interval to wait before shutting down this outlet (seconds)"
VARDESC outlet.delay.start "Interval to wait before restarting this outlet (seconds)"
VARDESC outlet.1.id "Outlet system identifier"
VARDESC outlet.1.desc "Outlet description"
VARDESC outlet.1.switch "Outlet switch control"
VARDESC outlet.1.status "Outlet switch status"
VARDESC outlet.1.switchable "Outlet switch ability"
VARDESC outlet.1.autoswitch.charge.low "Remaining battery level to power off this outlet (percent)"
VARDESC outlet.1.delay.shutdown "Interval to wait before shutting down this outlet (seconds)"
VARDESC outlet.1.delay.start "Interval to wait before restarting this outlet (seconds)"
VARDESC outlet.2.id "Outlet system identifier"
VARDESC outlet.2.desc "Outlet description"
VARDESC outlet.2.switch "Outlet switch control"
VARDESC outlet.2.status "Outlet switch status"
VARDESC outlet.2.switchable "Outlet switch ability"
VARDESC outlet.2.autoswitch.charge.low "Remaining battery level to power off this outlet (percent)"
VARDESC outlet.2.delay.shutdown "Interval to wait before shutting down this outlet (seconds)"
VARDESC outlet.2.delay.start "Interval to wait before restarting this outlet (seconds)"
VARDESC driver.name "Driver name"
VARDESC driver.version "Driver version - NUT release"
VARDESC driver.version.internal "Internal driver version"
# FIXME: driver.parameter and driver.flag can have many possible members
#
# VARDESC driver.parameter.[[:alpha:]]+ "Driver parameter: <name>"
# VARDESC driver.flag.[[:alpha:]]+ "Driver flag: <name>"
VARDESC server.info "Server information"
VARDESC server.version "Server version"
CMDDESC load.off "Turn off the load immediately"
CMDDESC load.on "Turn on the load immediately"
CMDDESC shutdown.return "Turn off the load and return when power is back"
CMDDESC shutdown.stayoff "Turn off the load and remain off"
CMDDESC shutdown.stop "Stop a shutdown in progress"
CMDDESC shutdown.reboot "Shut down the load briefly while rebooting the UPS"
CMDDESC shutdown.reboot.graceful "Delay briefly then shut down the load while rebooting the UPS"
CMDDESC test.panel.start "Start testing the UPS panel"
CMDDESC test.panel.stop "Stop a UPS panel test"
CMDDESC test.failure.start "Start a simulated power failure"
CMDDESC test.failure.stop "Stop simulating a power failure"
CMDDESC test.battery.start "Start a battery test"
CMDDESC test.battery.start.quick "Start a quick battery test"
CMDDESC test.battery.start.deep "Start a deep battery test"
CMDDESC test.battery.stop "Stop the battery test"
CMDDESC calibrate.start "Start run time calibration"
CMDDESC calibrate.stop "Stop run time calibration"
CMDDESC bypass.start "Put the UPS in bypass mode"
CMDDESC bypass.stop "Take the UPS out of bypass mode"
CMDDESC reset.input.minmax "Reset minimum and maximum input voltage status"
CMDDESC reset.watchdog "Reset watchdog timer"
CMDDESC beeper.on "Obsolete (use beeper.enable)"
CMDDESC beeper.off "Obsolete (use beeper.disable or beeper.mute)"
CMDDESC beeper.enable "Enable the UPS beeper"
CMDDESC beeper.disable "Disable the UPS beeper"
CMDDESC beeper.mute "Temporarily mute the UPS beeper"
CMDDESC beeper.toggle "Toggle the UPS beeper"
CMDDESC outlet.1.load.off "Turn off the load on outlet 1 immediately"
CMDDESC outlet.1.load.on "Turn on the load on outlet 1 immediately"
CMDDESC outlet.2.load.off "Turn off the load on outlet 2 immediately"
CMDDESC outlet.2.load.on "Turn on the load on outlet 2 immediately"
# The following two commands should *only* be defined when you need
# to compose a 'shutdown.return' command by sending both a switch-off
# with delay and a switch-on with delay command to the UPS. If this
# can be done with a single command, use 'shutdown.return' instead.
# Note that the switch-on with delay command *must not* turn on the
# load if the UPS is on battery.
#
CMDDESC load.off.delay "Turn off the load with a delay (seconds)"
CMDDESC load.on.delay "Turn on the load with a delay (seconds)"

725
data/driver.list Normal file
View file

@ -0,0 +1,725 @@
# Network UPS Tools driver.list
#
# This file is used to build the compat.html on the web server. Any line
# with exactly 4 arguments will be turned into an entry on there.
# Naturally, it is read by parseconf, so the usual escaping tricks are
# allowed if you need to insert something unusual.
#
# If you write a new driver, modify an existing one to add more support,
# or just know about some equipment that isn't listed but should be,
# please send me a patch to update this file.
#
# The format:
#
# <manufacturer> <model name> <model extra> <driver>
#
# Note that the "upstype=nn" format must be used for genericups entries,
# as they will be parsed by new configuration helper software.
#
# 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" "MS-RT" "" "megatec"
"Ablerex" "625L" "USB" "megatec_usb"
"Ablerex" "Hope Office 400/600" "" "megatec"
"ActivePower" "400VA" "" "megatec"
"ActivePower" "1400VA" "" "megatec"
"ActivePower" "2000VA" "" "megatec"
"Advice" "TopGuard 2000" "" "megatec"
"AEC" "MiniGuard UPS 700" "Megatec M2501 cable" "genericups upstype=21"
"APC" "Back-UPS Pro" "" "apcsmart"
"APC" "Matrix-UPS" "" "apcsmart"
"APC" "Smart-UPS" "" "apcsmart"
"APC" "Back-UPS Pro USB" "USB" "usbhid-ups"
"APC" "Back-UPS USB" "USB" "usbhid-ups"
"APC" "Back-UPS RS USB" "USB" "usbhid-ups"
"APC" "Back-UPS LS USB" "USB" "usbhid-ups"
"APC" "Back-UPS ES/CyberFort 350" "USB" "usbhid-ups"
"APC" "Back-UPS BF500" "USB" "usbhid-ups"
"APC" "BACK-UPS XS LCD" "USB" "usbhid-ups"
"APC" "Smart-UPS USB" "USB" "usbhid-ups"
"APC" "Back-UPS" "940-0095A/C cables" "genericups upstype=1"
"APC" "Back-UPS" "940-0020B/C cables" "genericups upstype=2"
"APC" "Back-UPS" "940-0023A cable" "genericups upstype=9"
"APC" "Back-UPS Office" "940-0119A cable" "genericups upstype=12"
"APC" "Back-UPS RS 500" "custom non-USB cable" "genericups upstype=20"
"APC" "Masterswitch" "Not a UPS - 940-0020 cable" "genericups upstype=12"
"APC" "AP9210" "8 outlets" "powerman-pdu (experimental)"
"APC" "AP79xx" "8 to 24 outlets" "powerman-pdu (experimental)"
"APC" "(various)" "SNMP monitoring card" "snmp-ups (experimental)"
"Aphel" "PDU" "no report, but various models should be supported" "snmp-ups (experimental)"
"Apollo" "1000A" "" "genericups upstype=4"
"Apollo" "1000F" "" "genericups upstype=4"
"Appro" "SWPDU" "48 outlets" "powerman-pdu (experimental)"
"Atlantis Land" "A03-P826" "" "megatec"
"Baytech" "RPC3" "8 outlets" "powerman-pdu (experimental)"
"Baytech" "RPC3-20NC" "8 outlets" "powerman-pdu (experimental)"
"Baytech" "RPC28-30NC" "20 outlets" "powerman-pdu (experimental)"
"Baytech" "various RPC" "" "snmp-ups"
"Belkin" "Active Battery Backup BU30 series" "USB" "megatec_usb"
"Belkin" "Home Office F6H350-SER" "" "genericups upstype=7"
"Belkin" "Home Office F6H500-SER" "" "genericups upstype=7"
"Belkin" "Home Office F6H650-SER" "" "genericups upstype=7"
"Belkin" "F6H375-USB" "USB (<= 2005 models, vendor id: 050d)" "usbhid-ups"
"Belkin" "F6H375-USB" "USB (2007 models, vendor id: 0665)" "megatec_usb"
"Belkin" "Office Series F6C550-AVR" "USB" "usbhid-ups"
"Belkin" "Regulator Pro" "F6C525-SER, F6C625-SER" "belkin"
"Belkin" "Resource" "" "genericups upstype=4"
"Belkin" "Small Enterprise F6C1500-TW-RK" "serial port" "belkin"
"Belkin" "Small Enterprise F6C1500-TW-RK" "USB" "usbhid-ups"
"Belkin" "Universal UPS F6C100-UNV" "USB" "usbhid-ups"
"Belkin" "Universal UPS F6C120-UNV" "serial port" "belkinunv"
"Belkin" "Universal UPS F6C120-UNV" "USB" "usbhid-ups"
"Belkin" "Universal UPS F6C800-UNV" "serial port" "belkinunv"
"Belkin" "Universal UPS F6C800-UNV" "USB" "usbhid-ups"
"Belkin" "Universal UPS F6C1100-UNV" "serial port (<= 2005 models)" "belkinunv"
"Belkin" "Universal UPS F6C1100-UNV" "USB (<= 2005 models, vendor id: 050d)" "usbhid-ups"
"Belkin" "Universal UPS F6C1100-UNV" "USB (2007 models, vendor id: 0665)" "megatec_usb"
"Belkin" "Universal UPS F6C1200-UNV" "USB (<= 2005 models, vendor id: 050d)" "usbhid-ups"
"Belkin" "Universal UPS F6C1200-UNV" "USB (2007 models, vendor id: 0665)" "megatec_usb"
"Belkin" "Universal UPS F6H350deUNV" "serial port" "megatec"
"Belkin" "Universal UPS F6H350ukUNV" "serial port" "megatec"
"Belkin" "Universal UPS F6H500ukUNV" "serial port" "megatec"
"Belkin" "Universal UPS F6H650ukUNV" "serial port" "megatec"
"Best Power" "Fortress (old)" "" "bestfortress"
"Best Power" "Fortress (newer)" "" "bestups"
"Best Power" "Fortress Telecom" "" "bestups"
"Best Power" "Axxium Rackmount" "" "bestups"
"Best Power" "Patriot Pro" "" "bestups"
"Best Power" "Patriot Pro II" "" "bestups"
"Best Power" "Patriot" "INT51 cable" "genericups upstype=6"
"Best Power" "Micro-Ferrups" "" "bestuferrups"
"Best Power" "Fortress/Ferrups" "f-command support" "bestfcom"
"Chloride" "Desk Power 650" "serial port" "megatec"
"Cito Power" "CPG-SR1000" "" "megatec"
"Clary" "ST-800" "" "gamatronic"
"Compaq" "T1500h" "" "upscode2 use_pre_lf"
"Compaq" "R3000h" "" "upscode2"
"Compaq" "R3000 XR" "" "bcmxcp"
"Compaq" "R5500 XR" "" "bcmxcp"
"Cyber Power Systems" "320AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "500AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "650AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "700AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "800AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "850AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "900AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "1250AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "1500AVR" "" "powerpanel or cyberpower"
"Cyber Power Systems" "Power99" "" "genericups upstype=7"
"Cyber Power Systems" "550SL" "" "genericups upstype=7"
"Cyber Power Systems" "725SL" "" "genericups upstype=7"
"Cyber Power Systems" "CPS825VA" "" "powerpanel"
"Cyber Power Systems" "1100AVR" "" "powerpanel"
"Cyber Power Systems" "1200AVR" "" "powerpanel"
"Cyber Power Systems" "1500AVR-HO" "" "powerpanel"
"Cyber Power Systems" "PR2200" "" "powerpanel"
"Cyber Power Systems" "PR3000E" "" "powerpanel (experimental)"
"Cyber Power Systems" "685AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "800AVR" "USB" "usbhid-ups"
"Cyber Power Systems" "AE550" "USB" "usbhid-ups"
"Cyber Power Systems" "CP 1500C" "USB" "usbhid-ups"
"Cyber Power Systems" "OR2200LCDRM2U" "USB" "usbhid-ups"
"Cyber Power Systems" "Value 400E" "USB" "usbhid-ups"
"Cyber Power Systems" "Value 600E" "USB" "usbhid-ups"
"Cyber Power Systems" "Value 800E" "USB" "usbhid-ups"
"Cyclades" "PM8" "8 outlets" "powerman-pdu (experimental)"
"Cyclades" "PM10" "10 outlets" "powerman-pdu (experimental)"
"Dell" "Dell UPS Tower 500W LV / HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Tower 500W LV / HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack/Tower 1000W LV / HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack/Tower 1000W LV / HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack/Tower 1500W LV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack/Tower 1500W LV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack/Tower 1920W LV / HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack/Tower 1920W LV / HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack/Tower 2300W LV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack/Tower 2300W LV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack/Tower 2700W LV / HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack/Tower 2700W LV / HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Short Depth Rack 2700W High Efficiency Online LV / HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Short Depth Rack 2700W High Efficiency Online LV / HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack 3750W High Efficiency Online HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack 3750W High Efficiency Online HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack 4200W High Efficiency Online HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack 4200W High Efficiency Online HV" "Serial port" "newmge-shut"
"Dell" "Dell UPS Rack 5600W HV" "USB port" "usbhid-ups"
"Dell" "Dell UPS Rack 5600W HV" "Serial port" "newmge-shut"
"Delta" "GES602N" "" "belkin"
"Deltec" "PowerRite Pro II" "" "genericups upstype=15"
"Digital Loggers" "LPC, EPCR2, DIN" "8 outlets" "powerman-pdu (experimental)"
"Digitus" "DN-170020" "" "megatec"
"Dynamix" "UPS1700D" "" "megatec"
"Dynamix" "UPS-650VA" "" "megatec ignoreoff"
"Dynex" "975AVR" "" "genericups upstype=7"
"Dynex" "DX-800U" "USB" "usbhid-ups"
"Eaton" "Protection Station 500/650/800 VA" "USB" "usbhid-ups"
"Eaton" "Ellipse ASR USBS 600/750/1000/1500 VA" "USB cable" "usbhid-ups"
"Eaton" "Ellipse MAX USBS 600/850/1100/1500 VA" "USB cable" "usbhid-ups"
"Eaton" "Evolution 650/850/1150/1550/2000 VA" "USB port" "usbhid-ups"
"Eaton" "Evolution S 1250/1750/2500/3000 VA" "USB port" "usbhid-ups"
"Eaton" "EX 700/1000/1500 VA" "USB port" "usbhid-ups"
"Eaton" "EX 2200/3000/3000 XL VA" "USB port" "usbhid-ups"
"Eaton" "EX 1000 RT2U / 1500 RT2U" "USB port" "usbhid-ups"
"Eaton" "MX 5/8/10/15/20 kVA" "USB port" "usbhid-ups"
"Eaton" "Nova AVR 625/1250" "USB" "usbhid-ups"
"Eaton" "E Series NV UPS 400-2000 VA" "" "megatec_usb"
"Eaton" "E Series DX UPS 1-20 kVA" "" "mge-utalk"
"Eaton" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut or newmge-shut"
"Eaton" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut or newmge-shut"
"Eaton" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut or newmge-shut"
"Eaton" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut or newmge-shut"
"Eaton" "EX 700/1000/1500 VA" "Serial port" "mge-shut or newmge-shut"
"Eaton" "EX 2200/3000/3000 XL VA" "Serial port" "mge-shut or newmge-shut"
"Eaton" "EX 1000 RT2U / 1500 RT2U" "Serial port" "mge-shut or newmge-shut"
"Eaton" "MX 5/8/10/15/20 kVA" "Serial port" "mge-shut or newmge-shut"
"Eaton" "EX RT 1:1 7/11 kVA" "" "mge-shut or newmge-shut"
"Eaton" "EX RT 3:1 5/7/11 kVA" "" "mge-shut or newmge-shut"
"Eaton" "EX RT (XML/HTTP)" "NMC Transverse card (ref 66074)" "netxml-ups (experimental)"
"Eaton" "EX RT (SNMP)" "NMC Transverse card (ref 66074)" "snmp-ups (experimental)"
"Eaton" "BladeUPS (SNMP)" "ConnectUPS Web/SNMP Card" "snmp-ups (experimental)"
"Eaton" "various models (XML/HTTP mode)" "NMC Minislot (Ref 66102)" "netxml-ups (experimental)"
"Eaton" "various models (SNMP mode)" "NMC Minislot (Ref 66102)" "snmp-ups (experimental)"
"Eaton" "various models (XML/HTTP mode)" "SNMP/Web Minislot card (ref 66244)" "netxml-ups (experimental)"
"Eaton" "various models (SNMP mode)" "SNMP/Web Minislot card (ref 66244)" "snmp-ups (experimental)"
"Eaton" "ePDU Managed" "" "snmp-ups (experimental)"
"Eaton" "ePDU Monitored" "" "snmp-ups or netxml-ups"
"Eaton" "Powerware 9130" "" "bcmxcp or usbhid-ups"
"Effekta" "MI/MT/MH" "2502 cable" "megatec"
"Effekta" "RM2000MH" "" "megatec"
"Energy Sistem" "(various)" "" "megatec"
"ETA" "mini+UPS" "WinNT/Upsoft cable" "genericups upstype=7"
"ETA" "mini+UPS PRO" "UPS Explorer cable" "etapro"
"Ever UPS" "NET *-DPC" "" "everups"
"Ever UPS" "AP *-PRO" "" "everups"
"Ever-Power" "625/1000" "" "safenet"
"Exide" "NetUPS SE" "" "genericups upstype=15"
"Fenton Technologies" "PowerPal" "P-series" "safenet"
"Fenton Technologies" "PowerPal" "L-series" "megatec"
"Fenton Technologies" "PowerOn" "" "megatec"
"Fenton Technologies" "PowerPure" "" "megatec"
"Fairstone" "L525/L625/L750" "" "safenet"
"Fideltronik" "Ares 700 and larger" "" "genericups upstype=6"
"Fideltronik" "Other Ares models" "" "genericups upstype=19"
"Fiskars" "PowerRite MAX" "" "upscode2"
"Fiskars" "PowerServer 10" "" "upscode2"
"Fiskars" "PowerServer 30" "" "upscode2"
"Fiskars" "9200" "UPS Information Unit" "upscode2"
"Forza Power Technologies" "SL-1001" "USB" "megatec_usb"
"Gamatronic" "All models with alarm interface" "" "genericups upstype=22"
"Gamatronic" "G-SmartCompact 2000" "" "megatec"
"Gamatronic" "MP110/210" "" "gamatronic"
"Gamatronic" "MS-T" "" "gamatronic"
"Gamatronic" "MS" "" "gamatronic"
"Gamatronic" "µPS3/1" "" "gamatronic"
"Geek Squad" "GS1285U" "USB" "usbhid-ups"
"Gemini" "UPS625/UPS1000" "" "safenet"
"HP" "PowerTrust 2997A" "HP 5061-2575 cable" "apcsmart"
"HP" "R3000 XR" "" "bcmxcp"
"HP" "R5500 XR" "" "bcmxcp"
"HP" "R1500 G2" "" "bcmxcp"
"HP" "R/T 2200 G2" "" "usbhid-ups"
"HP" "T500" "older models" "bcmxcp_usb"
"HP" "T750 INTL" "" "usbhid-ups"
"HP" "T750" "older models" "bcmxcp_usb"
"HP" "HP3488 Switch/Control Unit" "" "powerman-pdu (experimental)"
"IBM" "Blade Center Management Module" "15 outlets" "powerman-pdu (experimental)"
"ICS" "8064 Ethernet Relay Interface" "16 outlets" "powerman-pdu (experimental)"
"INELT" "Monolith 1000LT" "" "megatec"
"Inform" "GUARD" "Line Interactive AP model" "powercom"
"Inform" "Guard S 1500AP" "" "megatec"
"Inform" "Informer Compact 1000VA" "" "megatec or blazer_ser"
"Infosec" "iPEL 350" "" "megatec"
"Infosec" "iPEL 500" "" "megatec"
"Infosec" "iPEL 750" "" "megatec"
"Infosec" "iPEL 1000" "" "megatec"
"Infosec" "500XP" "" "megatec"
"Infosec" "XP 500" "USB" "megatec_usb"
"Infosec" "XP 1000" "" "megatec"
"IPMI" "" "" "powerman-pdu (experimental)"
"Ippon" "Back Power Pro 400/500/600/700/800" "" "blazer_ser or megatec"
"Ippon" "Back Power Pro 400/500/600/700/800" "USB" "blazer_usb (experimental)"
"Ippon" "Back Comfo Pro 600/800" "" "blazer_ser or megatec"
"Ippon" "Back Comfo Pro 600/800" "USB" "blazer_usb (experimental)"
"Ippon" "Smart Power Pro 1000/1400/2000" "" "blazer_ser or megatec"
"Ippon" "Smart Power Pro 1000/1400/2000" "USB" "blazer_usb (experimental)"
"Ippon" "Smart Winner 750/1000/1500/2000/3000" "" "blazer_ser or megatec"
"Ippon" "Smart Winner 750/1000/1500/2000/3000" "USB" "blazer_usb (experimental)"
"Ippon" "(various)" "" "blazer_ser or megatec"
"Ippon" "(various)" "USB" "blazer_usb"
"IVT" "SCD series" "" "ivtscd"
"Jageson Technology" "Jasuny USPS" "" "genericups upstype=4"
"Kebo" "1200D/D Series" "" "megatec"
"Krauler" "UP-D1200VA" "USB" "megatec_usb ignoreoff"
"Krauler" "UP-M500VA" "USB" "megatec_usb"
"Lestar" "MD-800E" "" "megatec"
"Liebert" "ITON 600VA" "" "megatec"
"Liebert" "UPStation GXT2" "contact-closure cable" "liebert"
"Liebert" "GXT2-3000RT230" "" "liebertgxt2 (experimental)"
"Liebert" "PowerSure Personal XT" "USB" "usbhid-ups"
"Liebert" "PowerSure PSA" "USB" "usbhid-ups"
"LNXI" "Icebox" "10 outlets" "powerman-pdu (experimental)"
"Masterguard" "(various)" "" "masterguard"
"Maxxtro" "UPS 600 VA" "serial port" "megatec"
"Mecer" "ME-2000" "" "megatec"
"Meta System" "HF Line" "1..4 boards" "metasys"
"Meta System" "HF Line \/2" "5..8 boards" "metasys"
"Meta System" "HF Millennium 810" "" "metasys"
"Meta System" "HF Millennium 820" "" "metasys"
"Meta System" "HF TOP Line 910" "" "metasys"
"Meta System" "HF TOP Line 920" "" "metasys"
"Meta System" "HF TOP Line 930" "" "metasys"
"Meta System" "HF TOP Line 940" "" "metasys"
"Meta System" "HF TOP Line 950" "" "metasys"
"Meta System" "HF TOP Line 960" "" "metasys"
"Meta System" "HF TOP Line 970" "" "metasys"
"Meta System" "HF TOP Line 980" "" "metasys"
"Meta System" "ECO Network 750" "" "metasys"
"Meta System" "ECO Network 1000" "" "metasys"
"Meta System" "ECO Network 1050" "" "metasys"
"Meta System" "ECO Network 1500" "" "metasys"
"Meta System" "ECO Network 1800" "" "metasys"
"Meta System" "ECO Network 2000" "" "metasys"
"Meta System" "ECO Network 2100" "" "metasys"
"Meta System" "ECO Network 2500" "" "metasys"
"Meta System" "ECO Network 3000" "" "metasys"
"Meta System" "ECO 305" "" "metasys"
"Meta System" "ECO 308" "" "metasys"
"Meta System" "ECO 311" "" "metasys"
"Meta System" "ECO 511" "" "metasys"
"Meta System" "ECO 516" "" "metasys"
"Meta System" "ECO 519" "" "metasys"
"Meta System" "ECO 522" "" "metasys"
"Meta System" "ally HF 800" "" "metasys"
"Meta System" "ally HF 1000" "" "metasys"
"Meta System" "ally HF 1250" "" "metasys"
"Meta System" "ally HF 1600" "" "metasys"
"Meta System" "ally HF 2000" "" "metasys"
"Meta System" "ally HF 2500" "" "metasys"
"Meta System" "Megaline 1250" "" "metasys"
"Meta System" "Megaline 2500" "" "metasys"
"Meta System" "Megaline 3750" "" "metasys"
"Meta System" "Megaline 5000" "" "metasys"
"Meta System" "Megaline 6250" "" "metasys"
"Meta System" "Megaline 7500" "" "metasys"
"Meta System" "Megaline 8750" "" "metasys"
"Meta System" "Megaline 10000" "" "metasys"
"MGE Office Protection Systems" "Protection Center 500/675 VA" "USB" "usbhid-ups"
"MGE Office Protection Systems" "Protection Station 500/650/800 VA" "USB" "usbhid-ups"
"MGE Office Protection Systems" "Ellipse ASR USBS 600/750/1000/1500 VA" "USB cable" "usbhid-ups"
"MGE Office Protection Systems" "Ellipse MAX USBS 600/850/1100/1500 VA" "USB cable" "usbhid-ups"
"MGE Office Protection Systems" "Evolution 650/850/1150/1550/2000 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "Evolution S 1250/1750/2500/3000 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "Pulsar 700/1000/1500 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "Pulsar M 2200/3000 VA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "Pulsar MX 5/8/10/15/20 kVA" "USB port" "usbhid-ups"
"MGE Office Protection Systems" "Ellipse ASR USBS 600/750/1000/1500 VA" "Serial cable" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Ellipse MAX USBS 600/850/1100/1500 VA" "Serial cable" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Evolution 650/850/1150/1550/2000 VA" "Serial port" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Evolution S 1250/1750/2500/3000 VA" "Serial port" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Pulsar 700/1000/1500 VA" "Serial port" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Pulsar M 2200/3000 VA" "Serial port" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Pulsar MX 5/8/10/15/20 kVA" "Serial port" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Comet EX RT 1:1 7/11 kVA" "" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Comet EX RT 3:1 5/7/11 kVA" "" "mge-shut or newmge-shut"
"MGE Office Protection Systems" "Comet EX RT (XML/HTTP)" "NMC Transverse card (ref 66074)" "netxml-ups (experimental)"
"MGE Office Protection Systems" "Comet EX RT (SNMP)" "NMC Transverse card (ref 66074)" "snmp-ups (experimental)"
"MGE Office Protection Systems" "various models (XML/HTTP mode)" "NMC Minislot (Ref 66102)" "netxml-ups (experimental)"
"MGE Office Protection Systems" "various models (SNMP mode)" "NMC Minislot (Ref 66102)" "snmp-ups (experimental)"
"MGE Office Protection Systems" "various models (XML/HTTP mode)" "SNMP/Web Minislot card (ref 66244)" "netxml-ups (experimental)"
"MGE Office Protection Systems" "various models (SNMP mode)" "SNMP/Web Minislot card (ref 66244)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "Comet EX RT" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Comet EX RT 3:1" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Protection Center 420" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Protection Center 500" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Protection Center 675" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "NOVA AVR 600 USB" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "NOVA AVR 1100 USB" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar Ellipse USBS" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar Ellipse USB" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar Ellipse Premium USBS" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar Ellipse Premium USB" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse Office 600" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse Office 750" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse Office 1000" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse Office 1500" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse MAX 600" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse MAX 850" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse MAX 1100" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Ellipse MAX 1500" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar Evolution" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution 650" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution 850" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution 1150" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution S 1250" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution 1550" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution S 1750" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution 2000" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution S 2500" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Evolution S 3000" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar M 2200" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar M 3000" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar M 3000 XL" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar 700" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar 1000" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar 1500" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar 1000 RT2U" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar 1500 RT2U" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar MX 4000 RT" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Pulsar MX 5000 RT" "USB" "usbhid-ups"
"MGE UPS SYSTEMS" "Comet / Galaxy (USB)" "USB Card (ref 66067)" "usbhid-ups"
"MGE UPS SYSTEMS" "NOVA AVR 600 Serial" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "NOVA AVR 1100 Serial" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Ellipse USBS" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Ellipse S" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Ellipse Premium USBS" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Ellipse Premium S" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse Office 600" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse Office 750" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse Office 1000" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse Office 1500" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse MAX 600" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse MAX 850" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse MAX 1100" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Ellipse MAX 1500" "Serial cable" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar EXtreme C / EX RT" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Comet EX RT" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Comet EX RT 3:1" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Esprit" "" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution 650" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution 850" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution 1150" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution S 1250" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution 1550" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution S 1750" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution 2000" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution S 2500" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Evolution S 3000" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar M 2200" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar M 3000" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar M 3000 XL" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar 700" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar 1000" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar 1500" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar 1000 RT2U" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar 1500 RT2U" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar MX 4000 RT" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar MX 5000 RT" "Serial port" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar Evolution" "Serial port" "mge-shut or newmge-shut or mge-utalk"
"MGE UPS SYSTEMS" "Pulsar EXtreme C" "" "mge-shut or newmge-shut or mge-utalk"
"MGE UPS SYSTEMS" "Pulsar ES+" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar ESV+" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar SV" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar ESV" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar EX" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar EXL" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar PSX" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar SX" "" "mge-utalk"
"MGE UPS SYSTEMS" "Pulsar EXtreme" "" "mge-utalk"
"MGE UPS SYSTEMS" "Comet EXtreme" "" "mge-utalk"
"MGE UPS SYSTEMS" "Comet / Galaxy (Serial)" "Utalk Serial Card (ref 66060)" "mge-utalk"
"MGE UPS SYSTEMS" "Comet / Galaxy (Serial)" "HID COM Serial Card (ref 66066)" "mge-shut or newmge-shut"
"MGE UPS SYSTEMS" "Pulsar / Comet / Galaxy (SNMP)" "SNMP/Web Transverse card (ref 66074)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "various models (XML/HTTP mode)" "NMC Minislot (Ref 66102)" "netxml-ups (experimental)"
"MGE UPS SYSTEMS" "various models (SNMP mode)" "NMC Minislot (Ref 66102)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "Pulsar (XML/HTTP mode)" "SNMP/Web Minislot card (ref 66244)" "netxml-ups (experimental)"
"MGE UPS SYSTEMS" "Pulsar (SNMP mode)" "SNMP/Web Minislot card (ref 66244)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "Pulsar / Comet / Galaxy (SNMP)" "SNMP card (ref 66062)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "Pulsar (SNMP)" "SNMP card (ref 66045)" "snmp-ups (experimental)"
"MGE UPS SYSTEMS" "UM-Link (SNMP)" "Not a UPS (ref 66850)" "snmp-ups (experimental)"
"MicroDowell" "B.Box BP 500" "" "powerpanel"
"MicroDowell" "B.Box BP 750" "" "powerpanel"
"MicroDowell" "B.Box BP 1000" "" "powerpanel"
"MicroDowell" "B.Box BP 1500" "" "powerpanel"
"MicroDowell" "Enterprise B8" "" "microdowell"
"MicroDowell" "Enterprise B10" "" "microdowell"
"MicroDowell" "Enterprise N8" "" "microdowell"
"MicroDowell" "Enterprise N11" "" "microdowell"
"MicroDowell" "Enterprise N15" "" "microdowell"
"MicroDowell" "Enterprise N20" "" "microdowell"
"MicroDowell" "Enterprise N22" "" "microdowell"
"MicroDowell" "Enterprise N30" "" "microdowell"
"MicroDowell" "Enterprise N40" "" "microdowell"
"MicroDowell" "Enterprise N50" "" "microdowell"
"MicroDowell" "Enterprise N60" "" "microdowell"
"MicroDowell" "Enterprise HiBox ST" "" "microdowell"
"Microsol" "Solis 1.0" "1000VA" "solis"
"Microsol" "Solis 1.5" "1500VA" "solis"
"Microsol" "Solis 2.0" "2000VA" "solis"
"Microsol" "Solis 3.0" "3000VA" "solis"
"Microsol" "Rhino 6.0" "6000VA" "rhino"
"Microsol" "Rhino 7.5" "7500VA" "rhino"
"Microsol" "Rhino 10.0" "10000VA" "rhino"
"Microsol" "Rhino 20.0" "20000VA" "rhino"
"Mustek" "Powermust" "400VA Plus" "megatec"
"Mustek" "Powermust" "600VA Plus" "megatec"
"Mustek" "Powermust" "800VA Pro" "megatec"
"Mustek" "Powermust" "1000VA Plus" "megatec"
"Mustek" "Powermust" "1400VA Plus" "megatec"
"Mustek" "Powermust" "2000VA USB" "megatec"
"Mustek" "Powermust Office 650" "USB" "megatec_usb"
"Mustek" "PowerMust 424 / 636 / 848" "USB" "blazer_usb"
"Mustek" "Various" "" "megatec"
"Neus" "400va / 600va" "" "megatec"
"Nitram" "Elite 500" "" "genericups upstype=8"
"Nitram" "Elite 2002" "" "genericups upstype=16"
"Nitram" "Elite 2005" "" "powerpanel"
"Oneac" "ON400" "advanced interface" "oneac"
"Oneac" "ON600" "advanced interface" "oneac"
"Oneac" "ON900" "advanced interface" "oneac"
"Oneac" "ON1300" "advanced interface" "oneac"
"Oneac" "EG Series" "advanced interface" "oneac"
"Oneac" "ON700" "advanced interface" "oneac"
"Oneac" "ON700XAU" "advanced interface" "oneac"
"Oneac" "ON700XIU" "advanced interface" "oneac"
"Oneac" "ON1000" "advanced interface" "oneac"
"Oneac" "ON1000XAU" "advanced interface" "oneac"
"Oneac" "ON1000XIU" "advanced interface" "oneac"
"Oneac" "ON1500" "advanced interface" "oneac"
"Oneac" "ON1500XAU" "advanced interface" "oneac"
"Oneac" "ON1500XIU" "advanced interface" "oneac"
"Oneac" "ON2000" "advanced interface" "oneac"
"Oneac" "ON2000XAU" "advanced interface" "oneac"
"Oneac" "ON2000XIU" "advanced interface" "oneac"
"Online" "P-Series" "" "genericups upstype=14"
"Online" "Zinto D" "" "optiups"
"OnLite" "AQUA" "50" "megatec"
"Opti-UPS" "PowerES" "420E" "optiups"
"Orvaldi Power Protection" "various" "not 400 or 600" "megatec"
"Phasak" "400VA / 600VA" "" "megatec"
"Plexus" "500VA" "USB" "megatec_usb ignoreoff"
"Plexus" "1000VA Pro" "USB" "megatec_usb ignoreoff"
"Powercom" "SMK" "" "megatec"
"Powercom" "SXL" "" "megatec"
"Powercom" "ULT" "" "megatec"
"Powercom" "Trust 425/625" "" "powercom"
"Powercom" "Advice Partner/King Pr750" "" "powercom"
"Powercom" "Black Knight PRO" "" "powercom"
"Powercom" "Black Knight PRO" "USB (2009 models, product id: 00a6)" "usbhid-ups (experimental)"
"Powercom" "Smart KING Pro (all Smart series)" "powercom"
"Powercom" "Smart KING Pro (all Smart series)" "USB (2009 models, product id: 00a3)" "usbhid-ups (experimental)"
"Powercom" "Imperial" "" "powercom"
"Powercom" "Imperial" "USB (2009 models, product id: 00a2)" "usbhid-ups (experimental)"
"Powercom" "Vanguard" "" "megatec"
"Powercom" "Vanguard" "USB (2009 models, product id: 00a5)" "usbhid-ups (experimental)"
"Powercom" "WOW" "USB (<= 2009 models, product id: 0002)" "powercom (requires 'usbserial' kernel module)"
"Powercom" "WOW" "USB (2009 models, product id: 00a4)" "usbhid-ups (experimental)"
"Powercom" "(various)" "USB (<= 2009 models, product id: 0002)" "powercom (requires 'usbserial' kernel module)"
"Powercom" "(various)" "USB (2009 models, product id: 00a?)" "usbhid-ups (experimental)"
"PowerGuard" "PG-600" "" "megatec"
"PowerKinetics" "9001" "" "genericups upstype=17"
"PowerKinetics" "BlackOut Buster" "" "megatec"
"PowerMan" "RealSmart 800" "" "megatec"
"PowerMan" "RealSmart 1000" "" "megatec"
"PowerMan" "BackPro" "" "genericups upstype=4"
"PowerTech" "Comp1000" "DTR cable power" "genericups upstype=3"
"PowerTech" "SMK-800" "" "megatec"
"PowerWalker" "Line-Interactive VI 1000" "" "megatec"
"PowerWalker" "Line-Interactive VI 400/800" "" "megatec"
"PowerWalker" "Line-Interactive VI 600" "" "megatec battvolts=9:13"
"Powerware" "3110" "" "genericups upstype=7"
"Powerware" "3115" "" "genericups upstype=11"
"Powerware" "5119, 5125" "" "genericups upstype=15"
"Powerware" "5119 RM" "" "genericups upstype=20"
"Powerware" "PW3105" "" "bcmxcp_usb"
"Powerware" "PW5110" "" "bcmxcp_usb"
"Powerware" "PW5115" "Serial port" "bcmxcp"
"Powerware" "PW5115" "USB port" "bcmxcp_usb"
"Powerware" "PW5125" "" "bcmxcp"
"Powerware" "PW9120" "Serial port" "bcmxcp"
"Powerware" "PW9120" "USB port" "bcmxcp_usb"
"Powerware" "PW9125" "" "bcmxcp"
"Powerware" "PW9315" "3-phase" "bcmxcp"
"Powerware" "9110" "" "upscode2"
"Powerware" "9120" "" "upscode2"
"Powerware" "9150" "" "upscode2"
"Powerware" "9305" "" "upscode2"
"Powerware" "BladeUPS (SNMP)" "ConnectUPS Web/SNMP Card" "snmp-ups (experimental)"
"Powerware" "(various)" "ConnectUPS Web/SNMP card" "snmp-ups (experimental)"
"Powerwell" "PM525A/-625A/-800A/-1000A/-1250A" "" "safenet"
"Phantom" "Rackable Systems" "1 outlets" "powerman-pdu (experimental)"
"Raritan" "Intelligent PDU - Dominion PX" "no report, but should be supported" "snmp-ups (experimental)"
"Raritan" "Metered PDU - Raritan PM" "no report, but should be supported" "snmp-ups (experimental)"
"Raritan" "Switched PDU - Raritan RPC" "no report, but should be supported" "snmp-ups (experimental)"
"Repotec" "RPF525/625/800/1000" "" "safenet"
"Repotec" "RPT-800A" "" "genericups upstype=13"
"Repotec" "RPT-162A" "" "genericups upstype=13"
"SmartLabs" "2412S Power Line Modem" "for X10/Insteon" "powerman-pdu (experimental)"
"SMS (Brazil)" "Manager III" "" "megatec"
"SOLA" "305" "cable INT-0025C" "genericups upstype=7"
"SOLA" "325" "" "bestups"
"SOLA" "520" "" "bestups"
"SOLA" "610" "use ID= in ups.conf" "bestups"
"SOLA" "620" "" "bestups"
"SOLA" "330" "" "megatec"
"SOLA/BASIC Mexico" "various" "ISBMEX protocol" "isbmex"
"Socomec" "NeTYS-PE 600VA" "megatec"
"Socomec Sicon" "Egys" "420 VA" "powercom"
"Socomec Sicon" "Netvision" "UPS equipped with Netvision WEB/SNMP card/external box" "snmp-ups (experimental)"
"Soltec" "Winmate 525/625/800/1000" "" "safenet"
"Soyntec" "Sekury C 500" "" "megatec"
"Soyntec" "Sekury C 800" "" "megatec"
"SquareOne Power" "QP1000" "" "megatec"
"Sun" "ILOM Management Module" "1 outlet" "powerman-pdu (experimental)"
"SuperPower" "HP360, Hope-550" "" "megatec"
"SVEN" "Power Pro+ series" "USB" "megatec_usb"
"SVEN" "Power Smart RM 2000" "USB" "megatec_usb"
"Sweex" "500/1000" "smart - shipped with SafeNet" "safenet"
"Sweex" "500/1000" "" "genericups upstype=7"
"Sweex" "1000" "USB" "richcomm_usb"
"Sweex" "(various)" "" "megatec"
"Sysgration" "UPGUARDS Pro650" "" "megatec"
"Tecnoware" "Easy Power 1200" "" "megatec"
"Tripp-Lite" "INTERNETOFFICE700" "USB" "tripplite_usb"
"Tripp-Lite" "OMNIVS1000" "USB" "tripplite_usb"
"Tripp-Lite" "OMNIVS1500XL" "USB" "tripplite_usb"
"Tripp-Lite" "SMART700USB" "USB" "tripplite_usb"
"Tripp-Lite" "SMART1500RM2U" "USB" "tripplite_usb"
"Tripp-Lite" "SMART550USB" "USB" "tripplite_usb"
"Tripp-Lite" "SMART2200RMXL2U" "USB, older models" "tripplite_usb (experimental)"
"Tripp-Lite" "SmartUPS" "" "tripplite"
"Tripp-Lite" "SmartOnline" "" "tripplitesu"
"Tripp-Lite" "(various)" "Lan 2.2 interface - black 73-0844 cable" "genericups upstype=5"
"Tripp-Lite" "OMNI1000LCD" "USB" "usbhid-ups"
"Tripp-Lite" "OMNI900LCD" "USB" "usbhid-ups"
"Tripp-Lite" "OMNI650LCD" "USB" "usbhid-ups"
"Tripp-Lite" "1500 LCD" "USB" "usbhid-ups"
"Tripp-Lite" "AVR550U" "USB" "usbhid-ups"
"Tripp-Lite" "AVR750U" "USB" "usbhid-ups"
"Tripp-Lite" "ECO550UPS" "USB" "usbhid-ups"
"Tripp-Lite" "SmartOnline SU1500RTXL2ua" "USB" "usbhid-ups"
"Tripp-Lite" "smart2200RMXL2U" "USB, newer models" "usbhid-ups"
"Trust" "UPS 1000 Management PW-4105" "" "megatec"
"Trust" "UPS 1200VA Management PW-4120M" "" "megatec"
"Trust" "UPS 1300VA Management PW-4130M" "" "megatec"
"UNITEK" "ALPHA 500 IC" "" "megatec dtr=0 rts=1"
"UNITEK" "Alpha 1000is" "" "megatec"
"UNITEK" "Alpha 500" "" "megatec"
"UNITEK" "Alpha 500 ipE" "" "megatec"
"UNITEK" "Alpha 2600" "" "megatec"
"UNITEK" "Alpha 1200Sx" "USB" "megatec_usb"
"UNITEK" "Alpha 1250xD" "USB" "megatec_usb"
"UPSonic" "CXR1000" "" "megatec"
"UPSonic" "LAN Saver 600" "" "genericups upstype=0"
"UPSonic" "Power Guardian" "" "genericups upstype=7"
"UPSonic" "PrOffice 650" "USB" "megatec_usb"
"UPSonic" "DS-800" "USB" "megatec_usb"
"Various" "(various)" "SEC protocol" "gamatronic"
"Various" "(various)" "Generic RUPS model" "genericups upstype=4"
"Various" "(various)" "Generic RUPS 2000 (Megatec M2501 cable)" "genericups upstype=21"
"Various" "(various)" "Q1 / Megatec protocol" "megatec"
"Various" "(various)" "PhoenixTec protocol" "bestups"
"Various" "(various)" "SNMP - RFC 1628" "snmp-ups (experimental)"
"Various" "(various)" "Safenet software" "safenet"
"Victron/IMV" "(various)" "" "victronups"
"Victron/IMV" "Lite" "crack cable" "genericups upstype=10"
"Viewsonic" "PowerES" "420E" "optiups"
"WinPower" "CPM-800" "" "megatec"
"WTI" "RPS-10" "10 outlets" "powerman-pdu (experimental)"
"WTI" "NPS" "8 outlets" "powerman-pdu (experimental)"

53
data/evolution500.dev Normal file
View file

@ -0,0 +1,53 @@
# dummy-ups example definition file ; generated with "upsc ups@host > evolution500.dev"
battery.charge: 90
battery.charge.low: 30
battery.runtime: 3690
battery.voltage: 230.0
driver.name: usbhid-ups
driver.parameter.port: auto
driver.version: 2.2.0
driver.version.data: MGE HID 0.7
driver.version.internal: 0.23
input.frequency: 49.0
input.transfer.boost.low: 184.0
input.transfer.high: 294.0
input.transfer.low: 160.0
input.transfer.trim.high: 265.0
input.voltage: 230.0
outlet.desc: Main Outlet
outlet.id: 0
outlet.switchable: 0
outlet.1.autoswitch.charge.low: 0
outlet.1.delay.shutdown: -1
outlet.1.delay.start: -1
outlet.1.desc: PowerShare Outlet 1
outlet.1.id: 1
outlet.1.switch: 1
outlet.1.switchable: 1
outlet.2.autoswitch.charge.low: 0
outlet.2.delay.shutdown: -1
outlet.2.delay.start: -1
outlet.2.desc: PowerShare Outlet 2
outlet.2.id: 2
outlet.2.switch: 1
outlet.2.switchable: 1
output.current: 0.00
output.frequency: 49.0
output.voltage: 230.0
output.voltage.nominal: 230.0
ups.delay.shutdown: -1
ups.delay.start: -10
ups.load: 10
ups.mfr: MGE UPS SYSTEMS
ups.model: Pulsar Evolution 500
ups.power.nominal: 500
ups.serial: AV2G3300L
ups.status: OL CHRG
ups.test.interval: 604800
ups.test.result: Done and passed
TIMER 300
ups.status: OB DISCHRG
TIMER 300
ups.status: OB LB DISCHRG
TIMER 60

7
data/html/Makefile.am Normal file
View file

@ -0,0 +1,7 @@
# Network UPS Tools: data/html
# install these only if configured --with-cgi
if WITH_CGI
dist_html_DATA = index.html bottom.html nut-banner.png
nodist_html_DATA = header.html
endif
EXTRA_DIST = README

488
data/html/Makefile.in Normal file
View file

@ -0,0 +1,488 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
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 = data/html
DIST_COMMON = README $(am__dist_html_DATA_DIST) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/header.html.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = header.html
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
am__dist_html_DATA_DIST = index.html bottom.html nut-banner.png
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(htmldir)" "$(DESTDIR)$(htmldir)"
DATA = $(dist_html_DATA) $(nodist_html_DATA)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
# Network UPS Tools: data/html
# install these only if configured --with-cgi
@WITH_CGI_TRUE@dist_html_DATA = index.html bottom.html nut-banner.png
@WITH_CGI_TRUE@nodist_html_DATA = header.html
EXTRA_DIST = README
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 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);; \
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):
header.html: $(top_builddir)/config.status $(srcdir)/header.html.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-dist_htmlDATA: $(dist_html_DATA)
@$(NORMAL_INSTALL)
test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"
@list='$(dist_html_DATA)'; test -n "$(htmldir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
done
uninstall-dist_htmlDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_html_DATA)'; test -n "$(htmldir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(htmldir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(htmldir)" && rm -f $$files
install-nodist_htmlDATA: $(nodist_html_DATA)
@$(NORMAL_INSTALL)
test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"
@list='$(nodist_html_DATA)'; test -n "$(htmldir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
done
uninstall-nodist_htmlDATA:
@$(NORMAL_UNINSTALL)
@list='$(nodist_html_DATA)'; test -n "$(htmldir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(htmldir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(htmldir)" && rm -f $$files
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(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 $(DATA)
installdirs:
for dir in "$(DESTDIR)$(htmldir)" "$(DESTDIR)$(htmldir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
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:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
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-dist_htmlDATA install-nodist_htmlDATA
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: uninstall-dist_htmlDATA uninstall-nodist_htmlDATA
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dist_htmlDATA install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-nodist_htmlDATA 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 uninstall uninstall-am uninstall-dist_htmlDATA \
uninstall-nodist_htmlDATA
# 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:

97
data/html/README Normal file
View file

@ -0,0 +1,97 @@
Desc: NUT HTML complementary information
File: README
Date: 27 Jul 2005
Auth: Arnaud Quette <arnaud.quette@free.fr>
Dave Breiland <superdave@dynamicis.com>
This file provides some complementary information
about the use and integration of NUT HTML pages.
1) Introduction
---------------
NUT HTML pages have been created as a central point
that ease the access to the various CGI scripts
providing the NUT web interface.
It consists of three .html files:
- index.html: defines the two container frames,
topFrame and mainFrame
- header.html: contain the header including links
to NUT website, and upsstat.cgi/upsset.cgi
- bottom.html: empty frame that will be replaced
with the content of upsstat.cgi or upsset.cgi.
2) Integration
--------------
You first need to install NUT CGI (ie using ./configure --with-cgi).
Refer to the README file for more information
There are two ways to integrate NUT HTML with your
webserver, with the same results:
a) take advantage of the existing tree
======================================
- the cgi are for example installed in /usr/lib/cgi-bin,
which is already configured in your webserver as the
default CGI path
- in the same spirit, we will use the existing DocumentRoot
and create a "nut" subdirectory, and copy the three .html
files (index, header and bottom)
Note that the links to cgi scripts in header.html are
pre configured to work in this situation, which ease
the packagers work.
b) configure manually
=====================
- copy the data/html directory to somepath (ie /usr/local/nut
for a standard installation from source)
-Now edit your webserver configuration file, adding for
example (for Apache):
#Begin Section
ScriptAlias /nut/cgi-bin/ /usr/local/nut/cgi-bin/
<Directory "/usr/local/nut/cgi-bin/">
AllowOverride AuthConfig
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
Alias /nut/ /usr/local/nut/html/
<Directory "/usr/local/nut/html/">
Options None
AllowOverride AuthConfig
Order allow,deny
Allow from all
</Directory>
#End Section
-Make sure to change the links path in header.html according to your
configuration and installation.
3) Conclusion
=============
- Make sure to restart your webserver.
-Configure the CGI scripts. Manpages can be found from:
--prompt> man -M /usr/local/nut/man/ upsstats.cgi
--prompt> man -M /usr/local/nut/man/ upsset.cgi
--prompt> man -M /usr/local/nut/man/ upsimage.cgi
--prompt> man -M /usr/local/nut/man/ hosts.conf
-It is recommended that you use .htaccess files in the cgi-bin folder and the
html folder. Please reference:
http://httpd.apache.org/docs/howto/htaccess.html
- You will then be able to access the NUT HTML page at:
http://localhost/nut

8
data/html/bottom.html Normal file
View file

@ -0,0 +1,8 @@
<HTML>
<HEAD>
<TITLE>
</TITLE>
</HEAD>
<BODY>
</BODY>
</HTML>

39
data/html/header.html.in Normal file
View file

@ -0,0 +1,39 @@
<html>
<head>
<title>
Network UPS Tools
</title>
</head>
<body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000EE" VLINK="#551A8B">
<table BGCOLOR="#50A0A0" ALIGN="CENTER">
<tr><td>
<table CELLPADDING="3">
<tr ALIGN=CENTER>
<th COLSPAN="2" BGCOLOR="#60B0B0">
<a href="http://www.networkupstools.org" target="new">
<IMG SRC="nut-banner.png"></a>
<br>
</th>
</tr>
<tr ALIGN=CENTER>
<td BGCOLOR="#00FFFF">
<a href=/cgi-bin/nut/upsstats.cgi target=mainFrame>Statistics</a>
</td>
<td BGCOLOR="#00FFFF">
<a href=/cgi-bin/nut/upsset.cgi target=mainFrame>Settings</a>
</td>
</tr>
</table>
</td></tr>
</table></body></html>

14
data/html/index.html Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Network UPS Tools -- http://www.networkupstools.org</title>
</head>
<frameset rows="110,*" frameborder="NO" border="0" framespacing="0">
<frame src="header.html" name="topFrame" scrolling="NO" noresize>
<frame src="bottom.html" name="mainFrame">
</frameset>
<noframes><body>
</body></noframes>
</html>

BIN
data/html/nut-banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

630
depcomp Executable file
View file

@ -0,0 +1,630 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2009-04-28.21; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 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
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://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
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputing dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u="sed s,\\\\\\\\,/,g"
depmode=msvisualcpp
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

822
docs/FAQ Normal file
View file

@ -0,0 +1,822 @@
Desc: Frequently Asked Questions
File: FAQ
Date: 20 January 2006
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <aquette.dev@gmail.com>
-----------------------------------------------------------------------------
Q: I just upgraded, and ...
A: You have read 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.
-----------------------------------------------------------------------------
Q: upsstats says "Error: can't open template file (upsstats.html)".
How do I fix this?
A: Go into your configuration path (/usr/local/ups/etc by default) and
copy the sample template files over to their real names. The sample
template files are installed with 'make install-cgi-conf' and can
also be found inside the source distribution in the conf directory.
-----------------------------------------------------------------------------
Q: upsmon fails the login and says "username required" now.
A: Go read the UPGRADING file again.
-----------------------------------------------------------------------------
Q: My 1.4 CGI programs won't talk to my 2.0 upsd. What should I do?
A: Upgrade the CGI programs to 2.0. While 1.4 was intended as a
compatibility tree that used the new protocol by default, the CGI
programs were not upgraded at the same time. The 1.4 versions
still use the old REQ protocol, and your 2.0 upsd expects GET.
-----------------------------------------------------------------------------
Q: I just upgraded from 1.2 and upsmon now fails to start, saying
"Fatal error: insufficient power configured!". Why?
A: You didn't read the top of the error, where upsmon says that it
ignored the invalid MONITOR line because UPS directives now require
a UPS name. It also means you didn't see the same warning in
UPGRADING.
At least you saw this in the FAQ before asking the list.
-----------------------------------------------------------------------------
Q: My UPS driver now says it's "broken", and won't start. What now?
Q: My favorite UPS driver disappeared after an upgrade. What now?
A: Drivers are occasionally removed from the tree if they are no longer
receiving maintenance, or sometimes renamed to better reflect their
hardware support scope or replaced by a more generic driver.
There have been several architectural changes to the driver code
in recent times, and drivers which were not converted by someone
are eventually dropped.
This is called progress. We do this in order to avoid a situation
where someone believes that a driver is being maintained when it is
actually rotting slowly in the tree. It also keeps the tree free of
old compatibility hacks for code that nobody actually uses anyway.
To get a driver back into current releases, you need to convert it
yourself or get someone to do it for you. This is not difficult.
The hardest part of any driver is decoding the protocol, and that's
already been done in the old version.
-----------------------------------------------------------------------------
Q: I just upgraded and now I can't talk to older versions.
A: Version 2.0 can't communicate with anything before 1.4 due to the
protocol changes. Version 1.4 can communicate with both 2.0 and
most older versions since it was a transitional release and has
compatibility code for both protocols.
-----------------------------------------------------------------------------
Q: My UPS driver program won't work. I'm starting it as root, and root
owns the device, so what's the problem?
A: The drivers drop root privileges long before the serial port is
opened. You'll need to change the permissions on that port so that
their new user id can access it. Normally this is "nobody", but it
may be changed at compile-time by using configure --with-user.
Read the error message. If you have a permissions mismatch, then
you'll see something like this:
Network UPS Tools - APC Smart protocol driver 0.60 (1.1.7)
This program is currently running as youruid (UID 1234)
/dev/ttyS2 is owned by user root (UID 0), mode 0600
Change the port name, or fix the permissions or ownership
of /dev/ttyS2 and try again.
Unable to open /dev/ttyS2: Permission denied
Now is a good time to point out that using "nobody" is a bad idea,
since it's a hack for NFS access. You should create a new role
account (perhaps called "ups" or "nut"), and use that instead.
Also, scroll down to the "security domains" question to see an
even better way of restricting privileged operations. Neither the
drivers nor upsd ever need root powers, and that answer tells you
how to make it work.
A: You can also specify a user with "user=" in the global part of
ups.conf. Just define it before any of your [sections]:
user = nut
[myups]
driver = mge-shut
port = /dev/ttyS0
-----------------------------------------------------------------------------
Q: upsc, upsstats, and the other clients say "access denied". The device
communication port (serial, USB or network) permissions are fine, so what
gives?
A: In this case, "access denied" means the access to upsd, not the device
communication port. You're being denied since the system has no
permission to speak to upsd according to the access controls.
There can be various reasons. To fix it, check:
- the LISTEN directive in upsd.conf. It should allow your local or remote
access method,
- your firewall rules. Port 3493/tcp must be opened to incoming connexions,
- your tcp-wrappers configuration (hosts.allow and hosts.deny).
Refer to the upsd(8) and upsd.conf(5) manpages for more information.
-----------------------------------------------------------------------------
Q: I have an APC Smart-UPS connected with a grey APC cable and it won't
work. 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?
A: The problem lies in your choice of cable. APC's grey cables
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.
Note that the 940-0095B happens to be a grey cable, but it is actually
a dual mode cable and can be used in smart mode. If you have
this cable, you need to edit your ups.conf to look like this:
[myups]
driver = apcsmart
port = /dev/whatever
cable = 940-0095B
All other grey cables from APC are assumed to be "dumb".
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.
See this URL for a handy diagram:
http://random.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
you to build a good clone of APC's 940-0024C cable.
There are simpler solutions involving 3 wires that work just fine
too, but Powerchute won't find the loopback DTR-DCD and RTS-CTS and
will be annoyed. If you don't ever plan to use Powerchute, 3 wires
(RxD, TxD, GND) are sufficient.
It should also be noted that the genericups driver has no way to
detect the UPS, so it will fire up quite happily if it can open the
serial port. Merely having it start up is not necessarily an
indication of success. You should start it and then check the
status with upsc or similar to be sure that it's reading the
hardware properly.
-----------------------------------------------------------------------------
Q: Why does configure fail to find gd?
A: Recent versions of gd should be detected automatically through the
gdlib-config script. Note that gd 2.0.5 through 2.0.7 have an
unusable script, so upgrade to the newest version if you have one
of those installed.
If you're stuck with an older version of gd, you can use it if you
specify the flags manually. Look in gd's Makefile for "LIBS=",
then use that value when you call configure:
./configure --with-gd-libs="<whatever>" --with-cgi
If you don't have gd's Makefile available for some reason, you're
in for a lot of trial and error.
-----------------------------------------------------------------------------
Q: Why PNG? You used to generate GIF bars with upsimage back in 1998
or 1999...
A: http://www.burnallgifs.org/
-----------------------------------------------------------------------------
Q: Why doesn't upsd implement the functionality of upsmon? I have to
run THREE programs to monitor my UPS!
A: I try to follow the "tool for the job" philosophy. It may mean
more programs running, but the flexibility you get is usually
worth it.
Yes, the machine with the UPS attached will generally have 3
processes (driver, upsd, upsmon) running, but this design allows a
much bigger setup. Imagine a data room with a bunch of machines
all drawing power from the same UPS. The rest of them just run
upsmon.
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 data-room.txt for more configuration ideas and explanations.
A: If this really bothers you, roll up your sleeves and use the
sockdebug code to write a "upsmon" type program that sits on top of
the state sockets. It won't work over the network, but it means
you don't need upsd. It also means only one host can monitor the
UPS.
This is also a good option to consider if you can't use networked
monitoring code for security or safety reasons.
See ideas.txt for more on this and other related topics.
-----------------------------------------------------------------------------
Q: Why isn't upssched part of upsmon?
A: Most users will never have any reason to use upssched. It's
complicated, and getting it right for your situation can be tricky.
Having it live in a separate program saves resources and lets most
people avoid it completely.
-----------------------------------------------------------------------------
Q: Why doesn't upsmon send a SIGPWR signal to init so it can deal with
power events?
A: New versions of the init man page taken from the sysvinit package
are saying that usage of SIGPWR is discouraged, since /dev/initctl
control channel is the preferred way of communication.
A: The name of the game is portability. Not everyone's init handles
that kind of signalling gracefully. What's more, some admins
might want to do things differently even if they have that kind of
init running.
So, to be compatible, upsmon just invokes a shell command. If you
want to use init's SIGPWR stuff, just put the right "kill" line in
a shell script and make upsmon call it. Everyone wins.
-----------------------------------------------------------------------------
Q: Why can't upsset read my upsset.passwd file?
A: You have an old version of upsset installed, since the current
version doesn't use that file. Install a new version and then try
it again.
Be sure to secure your CGI directory as instructed in the
upsset.conf.
-----------------------------------------------------------------------------
Q: Why won't bestups talk to my Best Fortress UPS?
A: There are at least two different protocols being used for hardware
with very similar names. The bestups driver tends to support the
units built around the newer "PhoenixTec" protocol.
Previous releases of this software included a driver called
bestfortress which supported the older Best hardware. See the
earlier entries about updating old drivers which have been removed
from the tree.
-----------------------------------------------------------------------------
Q: What's this about "data stale"?
A: It means your UPS driver hasn't updated things in a little while.
upsd refuses to serve up data that isn't fresh, so you get the
errors about staleness.
If this happens to you, make sure your driver is still running.
Also look at the syslog. Sometimes the driver loses the connection
to the UPS, and that will also make the data go stale.
Note: some very slow machines have trouble keeping up with the
serial ports during periods of extreme load. My old 486 used to
flip between "stale" and "OK" while running backups.
If this happens a lot, you might consider cranking up DEADTIME
in the upsmon.conf to suppress some of the warnings for shorter
intervals. Use caution when adjusting this number, since it
directly affects how long you run on battery without knowing
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 man page.
In such cases, you can raise the value of MAXAGE to avoid these
warnings; try a value like 25 or 30.
-----------------------------------------------------------------------------
Q: Why do the client programs say "Driver not connected" when I try
to run them?
A: This means that upsd can't connect to the driver for some reason.
Your ups.conf entry might be wrong, or the driver might not be
running. Maybe your state path is not configured properly.
Check your syslog. upsd will complain regularly if it can't
connect to a driver, and it should say why it can't connect.
Note: if you jumped in with both feet and didn't follow the INSTALL
document, you probably started upsd by itself. You have to run
'upsdrvctl start' to start the drivers after configuring ups.conf.
-----------------------------------------------------------------------------
Q: Everything works perfectly during the shutdown, and the UPS comes
back on, but my system stays off. What's happening?
A: Assuming you don't have the problem in the next question, then you
probably have an ATX motherboard, have APM or ACPI enabled in your
kernel (assuming Linux here), and are reaching the 'halt' at the
bottom of your shutdown scripts.
Your machine obeys and shuts down, and stays down, since it
remembers the 'last state' when the UPS restarts.
One solution is to change your shutdown scripts so you never reach
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 ...)
if (test -f /etc/killpower)
then
/usr/local/ups/bin/upsdrvctl shutdown
sleep 600 # this should never return
# uh oh, we never got shut down! (power race?)
reboot
fi
halt -p
The other solution is to change your BIOS setting to "always power
on" instead of "last state", assuming that's possible.
-----------------------------------------------------------------------------
Q: My system has an ATX power supply. It will power off just fine, but
it doesn't turn back on. What can I do to fix this?
A: This depends on how clueful your motherboard manufacturer is, and
isn't a matter of the OS. You have to do one of the following
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
- 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
when the outage is over.
This might work, but it creates high produce bills.
If you can't use one of the first two options, give the board to
an enemy. Let them worry about it.
-----------------------------------------------------------------------------
Q: My PowerMac G4 won't power back up by itself (into Linux) after the
UPS shuts down. What can I do about this?
A: This is about the same situation as the ATX question above, only
worse. Earlier Macs apparently supported a hack where you could
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
Unfortunately, the hardware has evolved and there is no good
equivalent for this hack on today's systems.
If you find out how to do this, please send me some mail, since
this affects one of my systems and my stop-gap solution is getting
cranky.
Note: this question has been in the FAQ for over a year and
there's still no answer. Let me guess: everyone who runs a server
on Mac hardware has a team of trained monkeys, and feeds them
by growing bananas in the tropical environment formed by waste heat
from the equipment.
The rest of us are still waiting for the answer. Booting into the
Mac OS to frob the "file server" panel is not an acceptable
solution.
A: If you're on OS X, this is relatively simple to fix. Go to system
preferences, click on energy saver, click on the options tab, check
"Restart automatically after a power failure".
If you're on some other OS, hope they've figured out how to duplicate
the above in a non-simian manner.
-----------------------------------------------------------------------------
Q: I want to keep the drivers and upsd in their own security domains.
How can this be accomplished?
A: Using a few role accounts and a common group, you can limit access
to resources such as the serial port(s) leading to the UPS
hardware.
This is just an example. Change the values to suit your systems.
Create a user called 'nutdev' and another called 'nutsrv'. Put
them both in a group called 'nut'.
Change the owner of any serial ports that will be used to nutdev,
and set the mode to 0600. Then change the ownership of your state
directory (usually /var/state/ups) to nutdev.nut.
For my development system this yields the following /dev entries:
0 crw------- 1 nutdev tty 4, 64 Sep 3 17:11 /dev/ttyS0
0 crw------- 1 nutdev tty 4, 65 Sep 3 17:11 /dev/ttyS1
Switch to root, then start the drivers:
# /usr/local/ups/bin/upsdrvctl -u nutdev start
The listing for /var/state/ups then looks like this:
4 drwxrwx--- 2 nutdev nut 4096 Aug 20 18:37 .
4 drwxr-xr-x 4 root root 4096 May 14 21:20 ..
4 srw-rw---- 1 nutdev nut 0 Sep 3 17:10 apcsmart-ttyS0
4 srw-rw---- 1 nutdev nut 0 Sep 3 17:10 megatec-ttyS1
You may have to remove old socket or state files first if you are
changing to this security scheme from an older version. The drivers
will create new files with the right owners and modes.
Note that /var/state/ups is group writable since upsd will
place the upsd.pid file here.
You may have to change the groups of upsd.conf and upsd.users to
make them readable. These files should not be owned by nutsrv,
since someone could compromise the daemon and change the config
files. Instead, put nutsrv in a group ("nut" in this example), then
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
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 chroot.txt for more details.
-----------------------------------------------------------------------------
Q: What's the point of that 'security domains' concept above?
A: The point is limiting your losses. If someone should happen to
break into upsd in that environment, they should only gain access
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.
Why give would-be vandals any sort of help?
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.
-----------------------------------------------------------------------------
Q: How can I make upsmon shut down my system after some fixed interval?
A: 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 upssched.txt or the upssched man
page for some ideas.
-----------------------------------------------------------------------------
Q: Why doesn't upsmon shut down my system? I pulled the plug and nothing
happened.
A: Wait. upsmon doesn't consider a UPS to be critical until it's both
'on battery' and 'low battery' at the same time. This is by design.
Nearly every UPS supports the notion of detecting the low battery
all by itself. When the voltage drops below a certain point, it
_will_ let you know about it.
If your system has a really complicated shutdown procedure, you
might need to shut down before the UPS raises the low battery flag.
For most users, however, the default behavior is adequate.
Ask yourself this: why buy a nice big UPS with the matching battery
and corresponding runtime and then shutdown early? If anything, I'd
rather have a few more minutes running on battery during which the
power might return. Once the power's back, it's business as usual
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
this is what you really want to do.
-----------------------------------------------------------------------------
Q: The CGI programs report "access to that host is not authorized" -
what's going on?
A: Those programs need to see a host in your hosts.conf before they
will attempt communications. This keeps people from feeding it
random "host=" settings, which would annoy others with outgoing
connection attempts from your system.
If your hosts.conf turns out to be configured correctly with
MONITOR entries and all that, check the permissions. Your web
server may be running the CGI programs as a user that can't read
the file.
If you run your web server in a chroot jail, make sure the programs
can still read hosts.conf. You may have to copy it into the jail
for this to work. If you do that, make sure it's not writable by
any of the user accounts which run inside the jail.
-----------------------------------------------------------------------------
Q: upsd is running, so why can't I connect to it?
A: Assuming you haven't changed the TCP port number on the command line
or at compile-time, then you probably have some sort of firewall
blocking the connection.
upsd listens on TCP port 3493 by default.
-----------------------------------------------------------------------------
Q: How do you make upsmon reload the config file?
Q: How do you make upsd reload the config file?
A: 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
should only send signals to one of them. To be safe, read the pid
file.
-----------------------------------------------------------------------------
Q: I just bought a new WhizBang UPS that has a USB connector. How do
I monitor it?
A: There are several driver to support USB models.
- usbhid-ups supports various manufacturers complying to the HID standard,
- tripplite_usb supports various Tripp-Lite units,
- bcmxcp_usb supports various Powerware units.
Refer to the "driver-name" (8) manpage for more information.
-----------------------------------------------------------------------------
Q: What is this usbhid-ups (formerly newhidups) about?
A: The basic USB UPS support was done until NUT 2.2 using hidups. To allow
a wider support accross platforms for USB/HID compliant devices,
usbhid-ups driver uses libusb (which is available for a wide range of
operating systems) and libhid (currently, a modified internal version
of it).
As of NUT 2.2, usbhid-ups completely replaces the legacy hidups driver
and provide support for various manufacturers. At that time, it will
be renamed to usbhid-ups.
usbhid-ups is built automatically if possible (libusb development files
need to be installed) and installed by the "make install" command.
-----------------------------------------------------------------------------
Q: Why doesn't my package work?
Q: I can't run this because there's no package for it. Why isn't this
in a package yet?
A: Sorry, can't help you there. All official releases are source code
and are posted on http://www.networkupstools.org/ along with PGP
signatures for verification.
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.
-----------------------------------------------------------------------------
Q: Why are there two copies of upsmon running?
A: It's not really two complete copies if your OS forks efficiently.
By default, upsmon runs most of the grunt work as an unprivileged
user and keeps a stub process around with root powers that can
only shut down the system when necessary. This should make it much
harder to gain root in the event a hole is ever discovered in
upsmon.
If this really bothers you and you like running lots of code as
root, start upsmon with -p and it will go back to being one big
process. This is not recommended, so don't blame me if something
bad happens in this mode.
-----------------------------------------------------------------------------
Q: I have <some problem> with <some old version> ...
A: Get the latest stable release, and see if it still happens. If it
goes away, it means someone else reported it and got it fixed a
long time ago.
If that doesn't work, try the latest development version.
If your problem is STILL there, then contact the mailing lists.
Hint: check the release date on the version you have. If it's more
than about 6 months old, there's probably a newer stable tree
version out there.
-----------------------------------------------------------------------------
Q: Do you have to use a serial connection to monitor the UPS?
What about direct network connections (SNMP or otherwise)?
A: No. NUT currently support USB communication through usbhid-ups,
tripplite_usb and bcmxcp_usb, and SNMP communication through snmp-ups.
Any time there is a gap in features, it's usually because the
group of people who own that hardware and the group of people who
write code don't overlap. The fix is to make them overlap -
turn an owner into a developer or vice-versa.
-----------------------------------------------------------------------------
Q: What happened to the patch I sent?
A: If a release goes by and your patch hasn't been included, it was
probably dropped. There can be a lot of patches waiting for
inclusion at some points, and occasionally some have to be
rejected.
Design issues or severe coding style problems can be the reason
for this. I try to point out what the problems are, but there are
limits. See developers.txt for some pointers on submitting
patches.
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.
-----------------------------------------------------------------------------
Q: I'm not much of a programmer. How can I help?
A: There's always work to be done outside of the realm of code bashing.
Documentation might not always be so clear. A user's perspective
is sometimes needed to appreciate this. Bug reports on a project's
documentation are just as valuable as those for the actual source.
Fielding questions on the mailing lists is also helpful. This
lets other people to focus on coding issues while allowing the
original poster to get some information at the same time. It's
quite a relief to open that mailbox and find that someone else
has already handled it successfully.
-----------------------------------------------------------------------------
Q: I replaced the battery in my APC Smart-UPS and now it thinks the
battery is low all the time. How do you fix this?
Q: My APC UPS keeps reporting "OL LB", even after it's been charging
for many hours. What can I do about this?
A: This happened to me, and some other people too. The combination of
our experiences should prove useful to you.
First, you need to realize that the UPS apparently stores data about
the battery, load, and runtime. After replacing the battery, it
needs to be clued in to the new situation. If the traditional
runtime calibration doesn't work, you have to try something a
little more drastic.
You need to *completely* drain the UPS while it has a good ground.
This means you can't just pull the plug. You also have to
disconnect it from the computer so this software won't shut it
down.
The easiest way to do this is to first unplug your computer(s) from
it, and plug in a token load like a lamp. Also, move the UPS to a
power strip that doesn't switch the ground line or an outlet that
you can switch off at your panel.
Once the UPS is up at 100% charge (this is important), disconnect
the power. It _must_ remain connected to the ground, or the
results may not be accurate. Ignore the sounds it makes, and go
away until it's done. Don't do anything to the front panel while
this is happening.
After all of this, put things back the way they should be and let
it charge up. You should find that it again gives reasonable
values and behavior, as it was when it was new.
Thanks to Matthew Dharm for helping me nail down this procedure.
-----------------------------------------------------------------------------
Q: multimon.cgi seems to be stuck at an old version, even though I
just installed a new one.
A: multimon was removed during the 1.1 development cycle. upsstats
now does everything it used to do, and then some. You should just
delete those files and start using upsstats directly.
-----------------------------------------------------------------------------
Q: OK, I switched to upsstats. Now it's giving me Celsius. I like
Fahrenheit. Where's the config file to switch it back?
A: Temperature scales are handled by the template files, so edit your
upsstats.html and change it from TEMPC to TEMPF.
-----------------------------------------------------------------------------
Q: Why is the mailing list ignoring me?
A: You probably asked a question that's answered in this FAQ or
somewhere else in the documentation and nobody wants to quote it
for you.
Convincing the other subscribers that you've actually read down this
far might be useful. You might mention "queequeg" for better results.
This URL may also be helpful:
http://www.catb.org/~esr/faqs/smart-questions.html
-----------------------------------------------------------------------------
Q: I found some information about another kind of UPS protocol you
don't support yet, but I don't know what to do with it. Can you
help?
A: 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.
-----------------------------------------------------------------------------
Q: How can you answer questions to situations that nobody's encountered
yet? Isn't this a frequently asked questions file?
A: Magic.
A: It's both that and a frequently *anticipated* questions file, too.
The idea is to write it up in here so that nobody asks the mailing
list when it finally does get released.
-----------------------------------------------------------------------------

13
docs/Makefile.am Normal file
View file

@ -0,0 +1,13 @@
# nothing to build here, but still need a Makefile to define which
# files to distribute
EXTRA_DIST = acpi.txt big-servers.txt chroot.txt \
commands.txt config-files.txt configure.txt contact-closure.txt \
data-room.txt design.txt developers.txt FAQ hid-subdrivers.txt \
ideas.txt macros.txt megatec.txt new-drivers.txt new-names.txt \
nut-hal.txt osd-notify.txt \
pager.txt powersaving.txt protocol.txt README shutdown.txt snmp.txt \
sock-protocol.txt ssl.txt upssched.txt cables/apc-rs500-serial.txt \
cables/apc.txt cables/ge-imv-victron.txt cables/imv.txt \
cables/mgeups.txt cables/powerware.txt cables/repotec.txt \
cables/sms.txt

423
docs/Makefile.in Normal file
View file

@ -0,0 +1,423 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
# nothing to build here, but still need a Makefile to define which
# files to distribute
VPATH = @srcdir@
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
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
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@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
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@
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@
docdir = @docdir@
driverexecdir = @driverexecdir@
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@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
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@
EXTRA_DIST = acpi.txt big-servers.txt chroot.txt \
commands.txt config-files.txt configure.txt contact-closure.txt \
data-room.txt design.txt developers.txt FAQ hid-subdrivers.txt \
ideas.txt macros.txt megatec.txt new-drivers.txt new-names.txt \
nut-hal.txt osd-notify.txt \
pager.txt powersaving.txt protocol.txt README shutdown.txt snmp.txt \
sock-protocol.txt ssl.txt upssched.txt cables/apc-rs500-serial.txt \
cables/apc.txt cables/ge-imv-victron.txt cables/imv.txt \
cables/mgeups.txt cables/powerware.txt cables/repotec.txt \
cables/sms.txt
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/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);; \
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
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(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:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
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)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
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 \
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 uninstall uninstall-am
# 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:

9
docs/README Normal file
View file

@ -0,0 +1,9 @@
When creating files in here, use the following 4 headers:
Desc: A brief description of the document
File: The filename (this is for tracking which one is the original)
Date: The date of last modification
Auth: The author, i.e. "First Last <foo@example.com>".
Note: anything in the form <.*@.*> will be removed when converted to HTML
to reduce the number of e-mail addresses harvested from the web servers.

32
docs/acpi.txt Normal file
View file

@ -0,0 +1,32 @@
Desc: Equivalence between ACPI and NUT variable naming
File: acpi.txt
Date: 30 September 2005
Auth: Arnaud Quette <aquette.dev@gmail.com>
This document presents an equivalence table between ACPI data
and NUT variable naming.
+-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityMode | percent | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.DesignCapacity | 100 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.FullChargeCapacity | 100 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Rechargeable | true / yes / 1 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.ConfigVoltage | output.voltage.nominal | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.WarningCapacityLimit | ? battery.charge.low | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacityLimit | battery.charge.low | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityGranularity1 | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityGranularity2 | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iProduct | ups.model | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iSerialNumber | ups.serial | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iDeviceChemistry | battery.type | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iOEMInformation | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Discharging | ups.status = DISCHRG | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Charging | ups.status = CHRG | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.BelowRemainingCapacityLimit | ups.status = LB | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Current | ? output.current | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacity | battery.charge | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Voltage | output.voltage | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacityLimit | battery.charge.low | +-------------------------------------------------------+---------------------------------------+
| PowerSummary.ACPresent | ups.status = OL |
+-------------------------------------------------------+---------------------------------------+

68
docs/big-servers.txt Normal file
View file

@ -0,0 +1,68 @@
Desc: Typical setups for big servers
File: big-servers.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
By using multiple MONITOR statements in upsmon.conf, you can configure
an environment where a large machine with redundant power monitors
multiple separate UPSes. For the examples in this document, I will use
a HP NetServer LH4 in the stock configuration with 3 of the 4 power
supplies installed.
Compared to some systems, the LH4 is unusual because it has common power
cords for multiple power supplies. One cord feeds two supplies. As a
result, each UPS drives two of the power supplies, so losing that UPS
affects both at the same time.
For our examples, UPS "Alpha" is connected to the cord that drives the
two power supplies, and ups "Beta" is connected to the other with just a
single power supply.
Since the server needs two supplies to stay alive, we can lose "Beta" at
any time, but losing "Alpha" is a showstopper. We make a note of them
when configuring upsmon:
MONITOR ups-alpha@myhost 2 monuser mypass master
MONITOR ups-beta@myhost 1 monuser mypass master
MINSUPPLIES 2
With that configuration, upsmon will only shut down when Alpha reaches
a critical (on battery + low battery) condition, since Beta by itself
is not enough to keep the system running. Beta, on the other hand,
can go up and down as much as it wants and nothing will happen as long
as the other one keeps working.
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).
Adding redundancy
=================
The above example assumed the stock hardware configuration. Let's say
we have successfully cajoled the boss into providing the money for a
fourth power supply. Now both power cords run two power supplies, and
the system is maxed out in terms of redundancy.
The upsmon.conf must be updated to reflect this:
MONITOR ups-alpha@myhost 2 monuser mypass master
MONITOR ups-beta@myhost 2 monuser mypass master
MINSUPPLIES 2
Beta is now driving two power supplies, so we upgrade its power value.
This means that either Alpha *or* Beta can totally shut down and the
server will be able to keep running.
As an added bonus, this means you can move a running server from one UPS
to another without bringing it down since the minimum power will be
provided at all times.
Other configurations
====================
There are a lot of ways to handle this and they all come down to how many
power supplies, power cords and independent UPS connections you have. A
system with a 1:1 cord:supply ratio has more wires stuffed behind it, but
it's much easier to move things around since any given UPS drives a smaller
percentage of the overall power.

View file

@ -0,0 +1,34 @@
Desc: APC UPS cable - for Back-UPS RS 500
File: apc-rs500-serial.txt
Date: 14 July 2004
Auth: Russell Kroll <rkroll@exploits.org>, Martin Edlman <edlman@fortech.cz>
This document was constructed from a mail from Martin. He figured out
the pinouts to make the Back-UPS RS 500 work with a normal serial port.
Here are the details:
---
UPS side PC side
RJ45 (8 pins) DB9F
1 orange/white 2,8,9
2 orange 1
3 green/white chassis/ground
4 blue -
5 blue/white -
6 green 5
7 brown/white 4,6
8 brown -
+---+
+-----+ +-----+
| |
+---------------+
8 7 6 5 4 3 2 1
view from back (cable entry)
---
Note this results in OL=-CTS, LB=DCD, SD=ST, CP=RTS, so it should work
with the existing genericups type 20.

233
docs/cables/apc.txt Normal file
View file

@ -0,0 +1,233 @@
Desc: APC UPS cables
File: apc.txt
Date: 12 Februari 2010
Auth: Arjen de Korte <adkorte-guest@alioth.debian.org
http://lists.alioth.debian.org/pipermail/nut-upsuser/2005-August/000118.html
+-----------------------------------------------------------------+
| |
| Black APC 940-0024C Smart Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<---------+----//----+----------------<(SHELL) |
| | | |
| - - |
| | | | | |
| CHASSIS 9<--------------//---------------------<5 SG |
| | | | | |
| TXD 2<--------------//---------------------<2 RXD |
| | | | | |
| RXD 1<--------------//---------------------<3 TXD |
| | | | | |
| - - +--<1 DCD |
| | |
| +--<4 DTR |
| NOTES: |
| Cable type is shielded 28AWG. +--<7 RTS |
| The DB shells are connected | |
| to each other via the shield. +--<8 CTS |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS communicates with the Computer via |
| ordinary RS-232 serial protocol at 2400-8N1 with software |
| flow control. Jumpered pins in the DB9F connector are for |
| automatic or PNP cable identification by UPS software. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Gray APC 940-0020B Simple Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<-------+----//----+-------------------<(SHELL) |
| | | |
| CHASSIS 9<--+ - - |
| | | | | | |
| COMMON 4<--+---------//------------------------<5 SG |
| | | | | |
| POWER-FAIL 2<------------//------------------------<8 CTS |
| | | | | |
| SHUTDOWN 1<------------//------------------------<4 DTR |
| | | | | |
| BATTERY-LOW 5<------------//--------47K--+--47K--+--<7 RTS |
| | | | | | | |
| - - | E | |
| NOTES: |B |<--+ |
| RTS must be held at +V SPACE. +---| |
| TXD must be held at -V MARK. 2N3906 |---+--<1 DCD |
| All resistors are 5% 1/8W CF. C | |
| Cable type is shielded 28AWG. 4K7 |
| The DB shells are connected | |
| to each other via the shield. +--<3 TXD |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS communicates with the Computer via |
| the RS-232 handshaking lines only, and does not use any |
| serial protocol. Upon power fail, the UPS forces CTS to |
| -V MARK. When the battery is low, the UPS forces DCD to |
| +V SPACE via the transistor. When the Computer forces a |
| +V SPACE on DTR, the UPS will shut down and turn off. |
| Presence of the cable can be sensed by signaling on TXD |
| while monitoring DCD. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Gray APC 940-0095A Smart Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<-------+----//----+--------------------<(SHELL) |
| | | |
| CHASSIS 9<--+ - - |
| | | | | | |
| COMMON 4<--+---------//-------------------------<5 SG |
| | | | | |
| BATTERY-LOW 5<------------//--------47K--+--47K--+---<4 DTR |
| | | | | | | |
| | +---<6 DSR |
| | | | | | E | |
| NOTES: |B |<--+---<8 CTS |
| DTR must be held at +V SPACE. | | +---| |
| TXD must be held at -V MARK. 2N3906 |---+---<1 DCD |
| All resistors are 5% 1/8W CF. | | C | |
| Cable type is shielded 28AWG. 4K7 |
| The DB shells are connected | | | |
| to each other via the shield. +----4K7---+---<3 TXD |
| | | | | | |
| | |
| | | | | | 1N4148 |
| SHUTDOWN 1<------------//----------+----|<|-------<7 RTS |
| | | | | K A |
| POWER-FAIL 2<------------//---------------------+---<2 RXD |
| | | | | | |
| - - +---<9 RI |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS can communicate with the Computer |
| solely via the RS-232 handshaking lines, or via RS-232 |
| serial protocol at 2400-8N1 with software flow control. |
| Upon power fail, the UPS forces RI to -V MARK. When the |
| battery is low, the UPS forces DCD to +V SPACE via the |
| transistor. When the Computer forces a +V SPACE on RTS, |
| the UPS will shut down and turn off. Jumpered pins in |
| the DB9F connector allow for automatic automatic or PNP |
| cable identification by UPS software. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Universal APC serial extension cable for use in conjunction |
| with an APC UPS cable. This cable is verified to work. |
| |
+-----------------------------------------------------------------+
| |
| DB9M to UPS cable Shielded Cable DB9F to Computer |
| ----------------- --- 28AWG ---- ---------------- |
| |
| (SHELL)<----+-------------//-------------+----<(SHELL) |
| | | |
| - - |
| | | | | |
| 1<------------------//------------------<1 DCD |
| | | | | |
| 2<------------------//------------------<2 RXD |
| | | | | |
| 3<------------------//------------------<3 TXD |
| | | | | |
| 4<------------------//------------------<4 DTR |
| | | | | |
| 5<------------------//------------------<5 SG |
| | | | | |
| 6<------------------//------------------<6 DSR |
| | | | | |
| 7<------------------//------------------<7 RTS |
| | | | | |
| 8<------------------//------------------<8 CTS |
| | | | | |
| 9<------------------//------------------<9 RI |
| | | | | |
| - - |
| NOTE: The DB shells are connected to each other via the shield. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+

View file

@ -0,0 +1,59 @@
Desc: IMV Victron UPS cables
File: victron.txt
Date: 13 April 2002
Auth: Daniel Prynych <Daniel.Prynych@hornet.cz>
Data cable 1 for UPS:
GE/IMV/Victron Match - 500 700 700L 1000 1000L 1500 2200 3000
GE/IMV/Victron NetPro (NetPro 19 ") - 600 1000 1200 2000 3000 4000
Driver: victronups (newvictronups)
UPS PC 9 pin [2~connector
1 --------- 3
2 --------- 2
5 --------- 5 GND
4 DTR
|
1 DCD
------------------------------------
Data cable 2 for UPS:
GE/IMV Victron Match Lite (all types)
Driver: victronups (newvictronups)
UPS PC 9 pin connector
2 --------- 3
3 --------- 2
4 --------- 5 GND
4 DTR
|
1 DCD
-----------------------------------
Crack cable: for UPS
Victron Lite (no IMV Victron Match Lite)
Driver: genericsups
UPS PC 9 pin connector
1 ---------- 4 DTR
7 ---------- 1 DCD ----------+
9 ---------- 8 CTS -----+ |
5 ---------- 5 GND | |
| |
R R 6,8k - 10k ohm
| |
7 RTS------+----+
----------------------------------------------
GE is General Electric Company.
On July 31, 2001, the General Electric Company, acquisited IMV (Victron) company.

12
docs/cables/imv.txt Normal file
View file

@ -0,0 +1,12 @@
Desc: IMV Match19 700 - 1500
File: imv.txt
Date: 06 April 2002
Auth: Niels S. Richthof <niels@richthof.de>
"UPS-VIC23-2" PC 9 pin connector
1 ---------------- 3
2 ---------------- 2
4 ---------------- 7
5 ---------------- 5

52
docs/cables/mgeups.txt Normal file
View file

@ -0,0 +1,52 @@
Desc: MGE UPS SYSTEMS serial cable
File: mgeups.txt
Date: 10 April 2002
Auth: Arnaud Quette <arnaud.quette@free.fr> or <arnaud.quette@mgeups.com>
This document describes the cable for MGE smart protocols : UTalk (ASCII),
and SHUT (Serial HID UPS Transfer, binary) .
First notice that MGE UPS SYSTEMS supply a standard cable, bundled with
the UPS unit and compatible with MS Windows and Unices (Ref 66049). For
more information, see below note about serial cable, PnP and Unix.
Cable description
-----------------
UPS COMPUTER
MALE DB9 FEMALE DB9
2 ---------------- 2 TX
3 ---------------- 3 RX
5 ---------------- 5 GND
-- 4
|
-- 6
-- 7
|
-- 8
UPS connector description
-------------------------
5 4 3 2 1
_______________
\o o o o o/
\ o o o o/
---------
9 8 7 6
9 pin Male DB-9 connector on UPS
Notes
-----
- this is a universal serial cable, so it should work with
any MGE serial model.
- max. length of cable is 1,80 m.
- Computer pin 6 (RTS) is reserved for PnP use, which could
trouble communication on some Unices if cabled. However, new
models (such as Ellipse, Evolution, Pulsar and Comet EXtreme,
EXtreme C, ...) handle this, so you can safely cable pin 6 or
use a standard (bundled) "windows" cable (Ref 66049).

26
docs/cables/powerware.txt Normal file
View file

@ -0,0 +1,26 @@
Desc: Powerware 3115 factory cable
File: powerware.txt
Date: 22 July 2005
Auth: various
1) Powerware 3115 factory cable
From Peter Åstrand <altic@lysator.liu.se>
UPS PC 9 pin connector
5 --------- 1
2 --------- 2
1 --------- 3
4 --------- 5
6 --------- 8
2) Powerware 5119 RM Cable Layout
From Daniel Thompson <danht@callthenet.com>
UPS <-----------> PC
DB9-M <--------> DB9-F
Pin 1 <-----------> Pin 3
Pin 2 <-----------> Pin 8
Pin 4 <-----------> Pin 4
Pin 5 <-----------> Pin 1
Shells Grounded Both Ends

26
docs/cables/repotec.txt Normal file
View file

@ -0,0 +1,26 @@
Desc: Repotec 800A (800VA) & 162A (1600VA) cable
File: repotec.txt
Date: 11 April 2001
Auth: Theodor Milkov <zimage@delbg.com>
PC UPS
1 (DCD) <----+---------- 2
|
R 5.6k
|
7 (RTS) >----+
3 (Tx) >--------------- 6
4 (DTR) <----+---------- 5
|
R 5.6k
|
8 (CTS) >----+
5 (GND) -------------+-- 4
|
+-- 7

16
docs/cables/sms.txt Normal file
View file

@ -0,0 +1,16 @@
Desc: SMS UPS cables, for Upsilon compatible SMS UPS
File: sms.txt
Date: 9 October 2001
Auth: Marcio Gomes <tecnica@microlink.com.br>
COMPUTER UPS
FEMEA DB9 MACHO DB9
2 ---------- 6
3 ---------- 9
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
- Use megatec driver from Nut Package

110
docs/chroot.txt Normal file
View file

@ -0,0 +1,110 @@
Desc: chrooting and other forms of paranoia
File: chroot.txt
Date: 24 August 2003
Auth: Russell Kroll <rkroll@exploits.org>
It has been possible to run the drivers and upsd in a chrooted jail for
some time, but it involved a number of evil hacks. The 1.3 series adds
much saner chroot behavior, using BIND 9 as an inspiration.
The old way involved creating an entire tree, complete with libraries, a
shell (!), and many auxiliary files. This was hard to maintain and
could have become an interesting playground for an intruder. The new
way is minimal, and leaves little in the way of usable materials within
the jail.
This document assumes that you already have created at least one user
account for the software to use. If you're still letting it fall back
on "nobody", stop right here and go figure that out first. It also
assumes that you have everything else configured and running happily all
by itself.
Essentially, you need to create your configuration directory and state
path in their own little world, plus a special device or two.
For the purposes of this example, the chroot jail is /chroot/nut. The
programs have been built with the default prefix, so they are using
/usr/local/ups. First, create the confpath and bring over a few files.
mkdir -p /chroot/nut/usr/local/ups/etc
cd /chroot/nut/usr/local/ups/etc
cp -a /usr/local/ups/etc/upsd.users .
cp -a /usr/local/ups/etc/upsd.conf .
cp -a /usr/local/ups/etc/ups.conf .
I'm using 'cp -a' to maintain the permissions on those files.
Now bring over your state path, maintaining the same permissions as
before.
mkdir -p /chroot/nut/var/state
cp -a /var/state/ups /chroot/nut/var/state
Next we must put /etc/localtime inside the jail, or you may get very
strange readings in your syslog. You'll know you have this problem if
upsd shows up as UTC in the syslog while the rest of the system doesn't.
mkdir -p /chroot/nut/etc
cp /etc/localtime /chroot/nut/etc
Note that this is not "cp -a", since we want to copy the *content*, not
the symlink that it may be on some systems.
Finally, create a tiny bit of /dev so the programs can enter the
background properly - they redirect fds into the bit bucket to make sure
nothing else grabs 0-2.
mkdir -p /chroot/nut/dev
cp -a /dev/null /chroot/nut/dev
Try to start your driver(s) and make sure everything fires up as before.
upsdrvctl -r /chroot/nut -u nutdev start
Once your drivers are running properly, try starting upsd.
upsd -r /chroot/nut -u nutsrv
Check your syslog. If nothing is complaining, try running clients like
upsc and upsmon. If they seem happy, then you're done.
symlinks
--------
After you do this, you will have two copies of many things, like the
confpath and the state path. I recommend deleting the 'real'
/var/state/ups, replacing it with a symlink to
/chroot/nut/var/state/ups. That will let other programs reference the
.pid files without a lot of hassle.
You can also do this with your confpath and point /usr/local/ups/etc at
/chroot/nut/usr/local/ups/etc unless you're worried about something
hurting the files inside that directory. In that case, you should
maintain a 'master' copy and push it into the chroot path after
making changes.
upsdrvctl itself does not chroot, so the ups.conf still needs to be in
the usual confpath.
upsmon
------
This has not yet been applied to upsmon, since it can be quite
complicated when there are notifiers that need to be run. One
possibility would be for upsmon to have three instances:
- privileged root parent that listens for a shutdown command
- unprivileged child that listens for notify events
- unprivileged chrooted child that does network I/O
This one is messy, and may not happen for some time, if ever.
Config files
------------
You may now set chroot= and user= in the global section of ups.conf.
upsd chroots before opening any config files, so there is no way to
add support for that in upsd.conf at the present time.

62
docs/commands.txt Normal file
View file

@ -0,0 +1,62 @@
Desc: Commands sent to the UPS drivers
File: commands.txt
Date: 9 January 2004
Auth: Russell Kroll <rkroll@exploits.org>
upsd can call drivers to store values in read/write variables and to kick
off instant commands. This is how you register handlers for those events.
The driver core (drivers/main.c) has a structure called upsh. You
should populate it with function pointers in your upsdrv_initinfo()
function. Right now, there are only two possibilities:
- setvar = setting UPS variables (SET VAR protocol command)
- instcmd = instant UPS commands (INSTCMD protocol command)
SET
---
If your driver's function for handling variable set events is called
my_ups_set(), then you'd do this to add the pointer:
upsh.setvar = my_ups_set;
my_ups_set() will receive two parameters:
const char * - the variable being changed
const char * - the new value
You should return either STAT_SET_HANDLED if your driver recognizes the
command, or STAT_SET_UNKNOWN if it doesn't. Other possibilities will be
added at some point in the future.
INSTCMD
-------
This works just like the set process, with slightly different values
arriving from the server.
upsh.instcmd = my_ups_cmd;
Your function will receive two args:
const char * - the command name
const char * - (reserved)
You should return either STAT_INSTCMD_HANDLED or STAT_INSTCMD_UNKNOWN
depending on whether your driver can handle the requested command.
Notes
-----
Use strcasecmp. The command names arriving from upsd should be treated
without regards to case.
Responses
---------
Drivers will eventually be expected to send responses to commands.
Right now, there is no channel to get these back through upsd to
the client, so this is not implemented.
This will probably be implemented with a polling scheme in the clients.

64
docs/config-files.txt Normal file
View file

@ -0,0 +1,64 @@
Desc: Details about the configuration files
File: config-files.txt
Date: 30 April 2003
Auth: Russell Kroll <rkroll@exploits.org>
All configuration files within this package are parsed with a common
state machine, which means they all can use a number of extras described
in this file.
First, most of the programs use an uppercase word to declare a
configuration directive. This may be something like MONITOR, NOTIFYCMD,
or ACCESS. The case does matter here. "monitor" won't be recognized.
Next, the parser does not care about whitespace between words. If you
like to indent things with tabs or spaces, feel free to do it here.
If you need to set a value to something containing spaces, it has to be
contained within "quotes" to keep the parser from splitting up the line.
That is, you want to use something like this:
SHUTDOWNCMD "/sbin/shutdown -h +0"
Without the quotes, it would only see the first word on the line.
OK, so let's say you really need to embed that kind of quote within your
configuration directive for some reason. You can do that too.
NOTIFYCMD "/bin/notifyme -foo -bar \"hi there\" -baz"
In other words, \ can be used to escape the ".
Finally, for the situation where you need to put the \ character into your
string, you just escape it.
NOTIFYCMD "/bin/notifyme c:\\dos\\style\\path"
The \ can actually be used to escape any character, but you only really
need it for \, ", and # as they have special meanings to the parser.
# is the comment character. Anything after an unescaped # is ignored.
Something like this...
identity = my#1ups
... will actually turn into "identity = my", since the # stops the
parsing. If you really need to have a # in your configuration, then
escape it.
identity = my\#1ups
Much better.
Line spanning
=============
You can put a backslash at the end of the line to join it to the next
one. This creates one virtual line that is composed of more than one
physical line.
Also, if you leave the "" quote container open before a newline, it will
keep scanning until it reaches another one. If you see bizarre behavior
in your configuration files, check for an unintentional instance of
quotes spanning multiple lines.

327
docs/configure.txt Normal file
View file

@ -0,0 +1,327 @@
Desc: Configure options
File: configure.txt
Date: 24 December 2008
Auth: Russell Kroll <rkroll@exploits.org>
Auth: Peter Selinger <selinger@sourceforge.net>
Auth: Arnaud Quette <aquette.dev@gmail.com>
There are a few options that can be given to configure to tweak compiles.
See also "./configure --help" for a current and complete listing.
Contents:
=========
1. Driver selection
2. Optional features
3. Other configuration options
4. Installation directories
5. Directories used by NUT at run-time
6. Things the compiler might need to find
1. Driver selection:
====================
--with-serial
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.
--with-snmp
Build and install the SNMP drivers (default: auto-detect)
Note that you need to install libsnmp development package or files.
--with-neon
Build and install the XML drivers (default: auto-detect)
Note that you need to install neon development package or files.
--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 (2006), there are 47 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 apcsmart 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.
2. Optional features:
=====================
--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
information on how to set up CGI programs.
--with-lib (default: no)
Build and install the upsclient library and header files.
--with-all (no default)
Build and install all of the above (the serial, USB, and SNMP
drivers, the CGI programs and HTML files, and the upsclient
library).
--with-ssl (default: auto-detect)
Enable SSL development code. Read docs/ssl.txt for instructions on
SSL support.
--with-wrap (default: auto-detect)
Enable libwrap (tcp-wrappers) support. Refer to upsd man page for
more information.
--with-ipv6 (default: auto-detect)
Enable IPv6 support.
--with-hal (default: no)
Build and install Hardware Abstraction Layer support.
If you own a USB unit, only protect your local system and run the
Gnome or KDE desktop, this will enable a full Plug & Play usage.
See docs/nut-hal.txt for additional information on how to set up
and use HAL support.
--with-powerman (default: auto-detect)
Build and install Powerman PDU client driver.
This allows to interact with the Powerman daemon, and the numerous
Power Distribution Units (PDU) supported by the project.
3. Other configuration options:
===============================
--with-port=PORT
Change the TCP port used by the network code. Default is 3493.
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.
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.
--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
time for the drivers.
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
(separate) process as the new user.
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".
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
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
you have to use the other one too.
See the INSTALL document and the FAQ for more on this topic.
--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.
4. Installation directories:
============================
--prefix=PATH
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.
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.
--exec_prefix=PATH
This sets the base path for architecture dependent files. By
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.
The NUT_CONFPATH environment variable overrides this at run time.
--bindir=PATH
--sbindir=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.
--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-lib 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.
--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.
The "driverpath" global directive in the ups.conf file overrides this
at run time.
--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.
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
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-lib 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-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
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-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
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.
5. 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.
--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.
--with-statepath=PATH
Change the default location of the state sockets created by the
drivers.
The NUT_STATEPATH environment variable overrides this at run time.
Default is /var/state/ups.
6. Things the compiler might need to find:
==========================================
--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.
--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.
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.
--with-ssl-includes, --with-usb-includes, --with-snmp-includes,
--with-neon-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.
--with-ssl-libs, --with-usb-libs, --with-snmp-libs,
--with-neon-libs, --with-powerman-libs="-L/foo/bar -labcd -lxyz"
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 linker flags that are needed.

108
docs/contact-closure.txt Normal file
View file

@ -0,0 +1,108 @@
Desc: Contact closure hardware
File: contact-closure.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
This is a collection of notes that apply to contact closure UPS
hardware, specifically those monitored by the genericups driver.
Definitions
-----------
"Contact closure" refers to a situation where one line is connected to
another inside UPS hardware to indicate some sort of situation. These
can be relays, or some other form of switching electronics. The generic
idea is that you either have a signal on a line, or you don't. Think
binary.
Usually, the source for a signal is the host PC. It provides a high
(logic level 1) from one of its outgoing lines, and the UPS returns it
on one or more lines to communicate. The rest of the time, the UPS
either lets it float or connects it to the ground to indicate a 0.
Other equipment generates the high and low signals internally, and does
not require cable power. These signals just appear on the right lines
without any special configuration on the PC side.
Bad levels
----------
Some evil cabling and UPS equipment uses the transmit or receive lines
as their reference points for these signals. This is not sufficient to
register as a high signal on many serial ports. If you have problems
reading certain signals on your system, make sure your UPS isn't trying
to do this.
Signals
-------
Unlike their smarter cousins, this kind of UPS can only give you very
simple yes/no answers. Due to the limited number of serial port lines
that can be used for this purpose, you typically get two pieces of data:
1. "On line" or "on battery"
2. "Battery OK" or "Low battery"
That's it. Some equipment actually swaps the second one for a
notification about whether the battery needs to be replaced, which makes
life interesting for those users.
Most hardware also supports an outgoing signal from the PC which means
"shut down the load immediately". This is generally implemented in such
a way that it only works when running on battery. Most hardware or
cabling will ignore the shutdown signal when running on line power.
New genericups types
--------------------
If none of the existing types in the genericups driver work completely,
make a note of which ones (if any) manage to work partially. This can
save you some work when creating support for your hardware.
Use that information to create a list of where the signals from your UPS
appear on the serial port at the PC end, and whether they are active
high or active low. You also need to know what outgoing lines, if any,
need to be raised in order to supply power to the contacts. This is
known as cable power. Finally, if your UPS can shut down the load, that
line must also be identified.
There are only 4 incoming and 2 outgoing lines, so not many combinations
are left. The other lines on a typical 9 pin port are transmit,
receive, and the ground. Anything trying to do a high/low signal on
those three is beyond the scope of the genericups driver. The only
exception is an outgoing BREAK, which we already support.
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_sd = what to set to make the UPS shut down the load
Incoming lines:
line_ol = flag that appears for on line / on battery
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
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
TIOCM_RNG, then the value of TIOCM_RNG (0x080 on my box) will be anded
with the value of the serial port whenever a poll occurs. If that flag
exists, then the result of the and will be 0x80. If it does not exist,
the result will be 0.
So, if line_ol = foo, then val_ol can only be foo or 0.
As a general case, if line_ol == val_ol, then the value you're reading
is active high. Otherwise, it's active low. Check out the guts of
upsdrv_updateinfo() to see how it really works.
Custom definitions
------------------
Late in the 1.3 cycle, a feature was merged which allows you to create
custom monitoring settings without editing the model table. Just set
upstype to something close, then use settings in ups.conf to adjust the
rest. See the genericups man page for more details.

54
docs/data-room.txt Normal file
View file

@ -0,0 +1,54 @@
Desc: Typical setups for data rooms
File: data-room.txt
Date: 27 May 2002
Auth: Russell Kroll <rkroll@exploits.org>
The split nature of this UPS monitoring software allows a wide variety of
power connections. This document will help you identify how things should
be configured using some general descriptions.
There are two main elements:
1. There's a UPS attached to a serial 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
for individual hosts:
A: 1 but not 2
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)
which depend on that same UPS for power, but aren't directly connected to
it.
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.
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.
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)
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.
Multi-power supply boxes
========================
If you are running large server-class systems that have more than one
power feed, see big-servers.txt for information on how to handle it
properly.

219
docs/design.txt Normal file
View file

@ -0,0 +1,219 @@
Desc: Network UPS Tools design document
File: design.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
This software is designed around a layered scheme with drivers, a
server and clients. These layers communicate with text-based
protocols for easier maintenance and diagnostics.
The layering
============
CLIENTS: upsmon, upsc, upsrw, upsstats, upsset, etc. (via upsclient)
< network: TCP sockets, typically on port 3493 >
SERVER: upsd
< Unix domain sockets with text-based messages >
DRIVERS: apcsmart, bestups, powercom, etc.
< serial communications, SNMP, USB, etc. >
EQUIPMENT: Smart-UPS 700, Fenton PowerPal 660, etc. (actual UPS hardware)
How information gets around
===========================
From the equipment
------------------
DRIVERS talk to the EQUIPMENT and receive updates. For most hardware this
is polled (DRIVER asks EQUIPMENT about a variable), but forced updates are
also possible. The exact method is not important, as it is abstracted
by the driver.
From the driver
---------------
The core of all DRIVERS maintains internal storage for every variable
that is known along with the auxiliary data for those variables. It
sends updates to this data to any process which connects to the Unix
domain socket.
The DRIVERS will also provide a full atomic copy of their internal
knowledge upon receiving the "DUMPALL" command on the socket. The dump
is in the same format as updates, and is followed by "DUMPDONE". When
"DUMPDONE" has been received, the view is complete.
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.
From the server
---------------
The SERVER's internal storage maintains a complete copy of the data
which is in the DRIVER, so it is capable of answering any request
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.
Instant commands
================
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 the front panel of the UPS.
They are passed to the SERVER from a CLIENT using an authenticated
network connection. The SERVER first checks to make sure that the instant
command is valid for the DRIVER. If it's supported, a message is sent
via a socket to the DRIVER containing the command and any auxiliary
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
fashion, so all queries must be lightweight and speedy.
Setting variables
=================
Some variables in the DRIVER or EQUIPMENT can be changed, and carry the
FLAG_RW flag. Upon receiving a SET command from the CLIENT, the SERVER
first verifies that it is valid for that DRIVER in terms of writability
and data type. If those checks pass, it then sends the SET command
through the socket, much like the instant command design.
The DRIVER is expected to commit the value to the EQUIPMENT and update
its internal representation of that variable.
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.
Example data path
=================
Here's the path a piece of data might take through this architecture.
The event is a UPS going on battery, and the final result is a pager
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
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
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".
5. CLIENT upsmon then invokes its NOTIFYCMD which is upssched.
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.
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
and then to the admin's pager.
This scenario requires some configuration, obviously:
1. There's a UPS driver running.
(Whatever applies for the hardware)
2. upsd has a valid UPS entry in ups.conf for this UPS.
[myups]
driver = upsdriver
port = /dev/ttySx
3. upsd has a valid user for upsmon in upsd.users.
[monuser]
password = somepass
upsmon master
4. upsmon is set to monitor this UPS in upsmon.conf.
MONITOR myups@localhost 1 monuser somepass master
5. upsmon is set to EXEC the NOTIFYCMD for the ONBATT condition in
upsmon.conf.
NOTIFYFLAG ONBATT EXEC
6. upsmon calls upssched as the NOTIFYCMD in upsmon.conf.
NOTIFYCMD /path/to/upssched
7. upssched has a 30 second timer for ONBATT in upssched.conf.
AT ONBATT * START-TIMER upsonbatt 30
8. upssched calls upssched-cmd as the CMDSCRIPT in upssched.conf.
CMDSCRIPT /path/to/upssched-cmd
8. upssched-cmd knows what to do with "upsonbatt" 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
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
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
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,
server) and a whole lot of locking and unlocking. It could occasionally
delay the driver or server when waiting for a lock.
In April 2003, the entire state management subsystem was removed and
replaced with a single local socket. The drivers listen for
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.
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.

374
docs/developers.txt Normal file
View file

@ -0,0 +1,374 @@
Desc: Information for developers
File: developers.txt
Date: 18 February 2004
Auth: Russell Kroll <rkroll@exploits.org>
This document is intended to explain some of the more useful things
within the tree and provide a standard for working on the code.
General stuff - common subdirectory
===================================
String handling
---------------
Use snprintf. It's even provided with a compatibility module if the
target host doesn't have it natively.
If you use snprintf to load some value into a buffer, make sure you
provide the format string. Don't use user-provided format strings,
since that's an easy way to open yourself up to an exploit.
Don't use strcat. We have a neat wrapper for snprintf called snprintfcat
that allows you to append to char * with a format string and all the usual
string length checking of snprintf.
Error reporting
---------------
Don't call syslog() directly. Use upslog_with_errno() and upslogx().
They may write to the syslog, stderr, or both as appropriate. This
means you don't have to worry about whether you're running in the
background or not.
upslog_with_errno prints your message plus the string expansion of
errno. upslogx just prints the message.
fatal_with_errno and fatalx work the same way, but they
exit(EXIT_FAILURE) afterwards. Don't call exit() directly.
Debugging information
---------------------
upsdebug_with_errno(), upsdebugx() and upsdebug_hex() use the
global nut_debug_level so you don't have to mess around with
printfs yourself. Use them.
Memory allocation
-----------------
xmalloc, xcalloc, xrealloc and xstrdup all check the results of the base
calls before continuing, so you don't have to. Don't use the raw calls
directly.
Config file parsing
-------------------
The configuration parser, called parseconf, is now up to its fourth
major version. It has multiple entry points, and can handle many
different jobs. It's usually used for parsing files, but it can also
take input a line at a time or even a character at a time.
You must initialize a context buffer with pconf_init before using any
other parseconf function. pconf_encode is the only exception, since it
operates on a buffer you supply and is an auxiliary function.
Escaping special characters and quoting multiple-word elements is all
handled by the state machine. Using the same code for all config files
avoids code duplication.
Note: this does not apply to drivers. Driver authors should use the
upsdrv_makevartable() scheme to pick up values from ups.conf. Drivers
should not have their own config files.
Drivers may have their own data files, such as lists of hardware,
mapping tables, or similar. The difference between a data file and a
config file is that users should never be expected to edit a data file
under normal circumstances. This technique might be used to add more
hardware support to a driver without recompiling.
<time.h> vs. <sys/time.h>
-------------------------
This is already handled by autoconf, so just include "timehead.h" and you
will get the right headers on every system.
UPS drivers - main.c
====================
The UPS drivers use main.c as their core. The only exception is
dummycons, which only looks like a driver by using the same dstate
function calls.
To write a new driver, you create a file with a series of support
functions that will be called by main. These all have names that start
with "upsdrv_", and they will be called at different times by main
depending on what needs to happen.
See new-drivers.txt for information on writing drivers, and also refer
to the skeletal driver in skel.c.
Portability
===========
Avoid things that will break on other systems. All the world is not an
x86 Linux box.
There are still older systems out there that don't do C++ style comments.
That means you have to comment /* like this */, and // this is right out.
Newer versions of gcc allow you to declare a variable inside a function
somewhat like the way C++ operates, like this:
function do_stuff(void)
{
check_something();
int a;
a = do_something_else();
}
While this will compile and run on these newer versions, it will fail
miserably for anyone on an older system. That means you must not use
it. gcc only warns about this with -pedantic.
Coding style
============
This is how I do things.
int open_subspace(char *ship, int privacy)
{
if (!privacy)
return insecure_channel(ship);
if (!init_privacy(ship))
fatal_with_errno("Can't open secure channel");
return secure_channel(ship);
}
(The example that used to be in this file wasn't particularly clear)
The basic idea is that I try to group things into functions, and then
find ways to drop out of them when we can't go any further. There's
another way to program this involving a big else chunk and a bunch of
braces, and it can be hard to follow. You can read this from top to
bottom and have a pretty good idea of what's going on without having to
track too much { } nesting and indenting.
I don't really care for pretentiousVariableNamingSchemes, but you can
probably get away with it in your own driver that I will never have to
touch. If your function or variable names start pushing important code
off the right margin of the screen, expect them to meet the byte
chainsaw sooner or later.
All types defined with typedef should end in "_t", because this is
easier to read, and it enables tools (such as indent and emacs) to
display the source code correctly.
Indenting with tabs vs. spaces
------------------------------
Another thing to notice is that the indenting happens with tabs instead
of spaces. This lets everyone have their personal tab-width setting
without inflicting much pain on other developers. If you use a space,
then you've fixed the spacing in stone and have really annoyed half of
the people out there.
If you write something that uses spaces, you may get away with it in a
driver that's relatively secluded. However, if I have to work on that
code, expect it to get reformatted according to the above.
Patches to existing code that don't conform to the coding style being
used in that file will probably be dropped. If it's something we really
need, it will be grudgingly reformatted before being included.
When in doubt, have a look at Linus's take on this topic in the Linux
kernel - Documentation/CodingStyle. He's done a far better job of
explaining this.
Line breaks
-----------
It is better to have lines that are longer than 80 characters than to
wrap lines in random places. This makes it easier to work with tools
such as "grep", and it also lets each developer choose their own
window size and tab setting without being stuck to one particular
choice.
Of course, this does not mean that lines should be made unnecessarily
long when there is a better alternative (see the note on
pretentiousVariableNamingSchemes above). Certainly there should not
be more than one statement per line. Please do not use
if (condition) break;
but use the following:
if (condition) {
break;
}
Miscellaneous coding style tools
--------------------------------
You can go a long way towards converting your source code to the NUT
coding style by piping it through the following command:
indent -kr -i8 -T FILE -l1000 -nhnl
This next command does a reasonable job of converting most C++ style
comments (but not URLs and DOCTYPE strings):
sed 's#\(^\|[ \t]\)//[ \t]*\(.*\)[ \t]*#/* \2 */#'
Emacs users can adjust how tabs are displayed. For example, it is
possible to set a tab stop to be 3 spaces, rather than the usual 8.
(Note that in the saved file, one indentation level will still
correspond to one tab stop; the difference is only how the file is
rendered on screen). It is even possible to set this on a
per-directory basis, by putting something like this into your .emacs
file:
;; NUT style
(defun nut-c-mode ()
"C mode with adjusted defaults for use with the NUT sources."
(interactive)
(c-mode)
(c-set-style "K&R")
(setq c-basic-offset 3) ;; 3 spaces C-indentation
(setq tab-width 3)) ;; 3 spaces per tab
;; apply NUT style to all C source files in all subdirectories of nut/
(setq auto-mode-alist (cons '(".*/nut/.*\\.[ch]$". nut-c-mode)
auto-mode-alist))
Finishing touches
-----------------
I like code that uses const and static liberally. If you don't need to
expose a function or global variable to the outside world, static is
your friend. If nobody should edit the contents of some buffer that's
behind a pointer, const keeps them honest.
We always compile with -Wall, so things like const and static help you
find implementation flaws. Functions that attempt to modify a constant
or access something outside their scope will throw a warning or even
fail to compile in some cases. This is what we want.
Spaghetti
---------
If you use a goto, expect me to drop it when my head stops spinning.
It gives me flashbacks to the BASIC code I wrote on the 8 bit systems of
the 80s. I've tried to clean up my act, and you should make the effort
as well.
I'm not making a blanket statement about gotos, since everything
probably has at least one good use. There are a few cases where a goto
is more efficient than any other approach, but you probably won't
encounter them in this software.
Hint: there *was* a good use of a goto in upsd until the 1.3 series. At
this point we are back to zero gotos since that code was replaced by
another technique that doesn't need it.
Legacy code
-----------
There are parts of the source tree that do not yet conform to these
specs. Part of this is due to the fact that the coding style has been
evolving slightly over the course of the project. Some of the code you
see in these directories is 5 years old, and things have gotten cleaner
since then. Don't worry - it'll get cleaned up the next time something
in the vicinity gets a visit.
Memory leak checking
--------------------
I can't say enough good things about valgrind. If you do anything with
dynamic memory in your code, you need to use this. Just compile with -g
and start the program inside valgrind. Run it through the suspected
area and then exit cleanly. valgrind will tell you if you've done
anything dodgy like freeing regions twice, reading uninitialized memory,
or if you've leaked memory anywhere.
http://valgrind.kde.org/
Conclusion
----------
The summary: please be kind to my eyes. There's a lot of stuff in here.
Submitting patches
==================
Patches that arrive in unified format (diff -u) as plain text with no
HTML, no attachments and a brief summary at the top are the easiest to
handle. They show the context, explain what's going on, and get saved as
one message. Everything stays together until it's time to merge.
Patches that arrive as attachments have to be moved around as separate
files - the body of the message is one, and the patch is in another.
This is not my preferred mode of operation.
When sending patches to the lists, be sure to add me as an explicit
recipient to make sure it is considered for merging. A patch which only
goes to a list is generally treated as a RFC and is relatively low
priority.
If your mailer is brain dead and rewrites tabs into spaces, wraps your
patch body, or anything else like that, just attach the patch. I'd
rather deal with an attachment instead of a patch that has tab damage,
rewrapped lines, or worse.
Patch cohesion
==============
Patches should have some kind of unifying element. One patch set is one
message, and it should all touch similar things. If you have to edit 6
files to add support for neutrino detection in UPS hardware, that's
fine.
However, sending one huge patch that does massive separate changes
all over the tree is not recommended. That kind of patch has to be
split up and evaluated separately, assuming I care enough to do that
instead of just dropping it.
If you have to make big changes in lots of places, send multiple
patches - one per item.
Man pages
=========
If you change something that involves an argument to a program or
configuration file parsing, the man page is probably now out of date.
If you don't update it, I have to, and I have enough to do as it is.
If you write a new driver, send in the man page when you send me the
source code for your driver. Otherwise, I will be forced to write a
skeletal man page that will probably miss many of the finer points of
the driver and hardware.
Repository etiquette and quality assurance
==========================================
Please keep the SVN trunk in working condition at all times. The trunk
may be used to generate daily tarballs, and should not contain broken
code if possible. If you need to commit incremental changes that leave
the system in a broken state, please do so in a separate branch and
merge the changes back to the trunk once they are complete.
Before committing, please remember to:
* update the ChangeLog, if appropriate. Dates are listed in UTC
("date --utc").
* run "make distcheck-light". This checks that the Makefiles are not
broken, that all the relevant files are distributed, and that there
are no compilation or installation errors.
Running "make distcheck-light" is especially important if you have
added or removed files, or updated configure.in or some Makefile.am.
Remember: simply adding a file to SVN does not mean it will be
distributed. To distribute a file, you must update the corresponding
Makefile.am.
There is also "make distcheck", which runs an even stricter set of
tests, but will not work unless you have all the optional libraries
and features installed.

221
docs/hid-subdrivers.txt Normal file
View file

@ -0,0 +1,221 @@
Desc: How to make a new subdriver to support another USB/HID UPS
File: hid-subdrivers.txt
Date: 08 January 2007
Auth: Peter Selinger <selinger@users.sourceforge.net>
Overall concept
===============
USB (Universal Serial Port) devices can be divided into several
different classes (audio, imaging, mass storage etc). Almost all UPS
devices belong to the "HID" class, which means "Human Interface
Device", and also includes things like keyboards and mice. What HID
devices have in common is a particular (and very flexible) interface
for reading and writing information (such as x/y coordinates and
button states, in case of a mouse, or voltages and status information,
in case of a UPS).
The Nut "usbhid-ups" driver is a meta-driver that handles all HID UPS
devices. It consists of a core driver that handles most of the work of
talking to the USB hardware, and several sub-drivers to handle
specific UPS manufacturers (MGE, APC, and Belkin are currently
supported). Adding support for a new HID UPS device is easy, because
it requires only the creation of a new sub-driver.
There are a few USB UPS devices that are not HID devices. These
devices typically implement some version of the manufacturer's serial
protocol over USB (which is a really dumb idea, by the way). An
example is the Tripplite USB. Such devices are *not* supported by the
usbhid-ups driver, and are not covered in this document. If you need to
add support for such a device, read new-drivers.txt and see the
tripplite_usb driver for inspiration.
HID Usage Tree
==============
From the point of view of writing a HID subdriver, a HID device
consists of a bunch of variables. Some variables (such as the current
input voltage) are read-only, whereas other variables (such as the
beeper enabled/disabled/muted status) can be read and written. These
variables are usually grouped together and arranged in a hierarchical
tree shape, similar to directories in a file system. This tree is
called the "usage" tree. For example, here is part of the usage tree
for a typical APC device. Variable components are separated by ".".
Typical values for each variable are also shown for illustrative
purposes.
UPS.Battery.Voltage 11.4 V
UPS.Battery.ConfigVoltage 12 V
UPS.Input.Voltage 117 V
UPS.Input.ConfigVoltage 120 V
UPS.AudibleAlarmControl 2 (=enabled)
UPS.PresentStatus.Charging 1 (=yes)
UPS.PresentStatus.Discharging 0 (=no)
UPS.PresentStatus.ACPresent 1 (=yes)
As you can see, variables that describe the battery status might be
grouped together under "Battery", variables that describe the input
power might be grouped together under "Input", and variables that
describe the current UPS status might be grouped together under
"PresentStatus". All of these variables are grouped together under
"UPS".
This hierarchical organization of data has the advantage of being very
flexible; for example, if some device has more than one battery, then
similar information about each battery could be grouped under
"Battery1", "Battery2" and so forth. If your UPS can also be used as a
toaster, then information about the toaster function might be grouped
under "Toaster", rather than "UPS".
However, the disadvantage is that each manufacturer will have their
own idea about how the usage tree should be organized, and usbhid-ups
needs to know about all of them. This is why manufacturer specific
subdrivers are needed.
To make matters more complicated, usage tree components (such as
"UPS", "Battery", or "Voltage") are internally represented not as
strings, but as numbers (called "usages" in HID terminology). These
numbers are defined in the "HID Usage Tables", available from
http://www.usb.org/developers/hidpage/. The standard usages for UPS
devices are defined in a document called "Usage Tables for HID Power
Devices".
For example,
0x00840010 = UPS
0x00840012 = Battery
0x00840030 = Voltage
0x00840040 = ConfigVoltage
0x0084001a = Input
0x0084005a = AudibleAlarmControl
0x00840002 = PresentStatus
0x00850044 = Charging
0x00850045 = Discharging
0x008500d0 = ACPresent
Thus, the above usage tree is internally represented as
00840010.00840012.00840030
00840010.00840012.00840040
00840010.0084001a.00840030
00840010.0084001a.00840040
00840010.0084005a
00840010.00840002.00850044
00840010.00840002.00850045
00840010.00840002.008500d0
To make matters worse, most manufacturers define their own additional
usages, even in cases where standard usages could have been used. for
example Belkin defines 00860040 = ConfigVoltage (which is incidentally
a violation of the USB specification, as 00860040 is reserved for
future use).
Thus, subdrivers generally need to provide:
- manufacturer-specific usage definitions,
- a mapping of HID variables to NUT variables.
Moreover, subdrivers might have to provide additional functionality,
such as custom implementations of specific instant commands (load.off,
shutdown.restart), and conversions of manufacturer specific data
formats.
Writing a subdriver
===================
In preparation for writing a subdriver for a device that is currently
unsupported, run usbhid-ups with the following command line:
drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX auto
(substitute your device's 4-digit VendorID instead of "XXXX").
This will produce a bunch of debugging information, including a number
of lines starting with "Path:" that describe the device's usage tree.
This information forms the initial basis for a new subdriver.
You should save this information to a file, e.g.
drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX auto >& /tmp/info
You can create an initial "stub" subdriver for your device by using
script scripts/subdriver/path-to-subdriver.sh. Note: this only creates
a "stub" and needs to be futher customized to be useful (see
CUSTOMIZATION below).
Use the script as follows:
scripts/subdriver/path-to-subdriver.sh < /tmp/info
where /tmp/info is the file where you previously saved the debugging
information.
This script prompts you for a name for the subdriver; use only letters
and digits, and use natural capitalization such as "Belkin" (not
"belkin" or "BELKIN"). The script may prompt you for additional
information.
You should put the generated files into the drivers/ subdirectory, and
update usbhid-ups.c by adding the appropriate #include line and by
updating the definition of subdriver_list in usbhid-ups.c. You must
also add the subdriver to USBHID_UPS_SUBDRIVERS in drivers/Makefile.am
and call "autoreconf" and/or "./configure" from the top level NUT directory.
You can then recompile usbhid-ups, and start experimenting with the new
subdriver.
CUSTOMIZATION: The initially generated subdriver code is only a stub,
and will not implement any useful functionality (in particular, it
will be unable to shut down the UPS). In the beginning, it simply
attempts to monitor some UPS variables. To make this driver useful,
you must examine the NUT variables of the form "unmapped.*" in the
hid_info_t data structure, and map them to actual NUT variables and
instant commands. There are currently no step-by-step instructions for
how to do this. Please look at the files
mge-hid.c/h
apc-hid.c/h
belkin-hid.c/h
to see how the currently implemented subdrivers are written.
Shutting down the UPS
=====================
It is desireable to support shutting down the UPS. Usually (for
devices that follow the HID Power Device Class specification), this
requires sending the UPS two commands. One for shutting down the UPS
(with an 'offdelay') and one for restarting it (with an 'ondelay'),
where offdelay < ondelay. The two NUT commands for which this is
relevant, are 'shutdown.return' and 'shutdown.stayoff'.
Since the one-to-one mapping above doesn't allow sending two HID
commands to the UPS in response to sending one NUT command to the
driver, this is handled by the driver. In order to make this work,
you need to define the following four NUT values:
ups.delay.start (variable, R/W)
ups.delay.shutdown (variable, R/W)
load.off.delay (command)
load.on.delay (command)
If the UPS supports it, the following variables can be used to show
the countdown to start/shutdown:
ups.timer.start (variable, R/O)
ups.timer.shutdown (variable, R/O)
The 'load.on' and 'load.off' commands will be defined implicitly by
the driver (using a delay value of '0'). Define these commands
yourself, if your UPS requires a different value to switch on/off
the load without delay.
Note that the driver expects the 'load.off.delay' and 'load.on.delay'
to follow the HID Power Device Class specification, which means that
the 'load.on.delay' command should NOT switch on the load in the
absence of mains power. If your UPS switches on the load regardless of
the mains status, DO NOT define this command. You probably want to
define the 'shutdown.return' and/or 'shutdown.stayoff' commands in
that case. Commands defined in the subdriver will take precedence over
the ones that are composed in the driver.
When running the driver with the '-k' flag, it will first attempt to
send a 'shutdown.return' command and if that fails, will fallback to
'shutdown.reboot'.

85
docs/ideas.txt Normal file
View file

@ -0,0 +1,85 @@
Desc: Ideas for future expansion and features
File: ideas.txt
Date: 20 October 2003
Auth: Russell Kroll <rkroll@exploits.org>
Here are some ideas that have come up over the years but haven't
been implemented yet. This may be a good place to start if you're
looking for a rainy day hacking project.
Non-network "upsmon"
====================
Some systems don't want a daemon listening to the network. This can be
for security reasons, or perhaps because the system has been squashed
down and doesn't have TCP/IP available. For these situations you could
run a driver and program that sits on top of the driver socket to do
local monitoring.
This also makes monitoring extremely easy to automate - you don't need
to worry about usernames, passwords or firewalling. Just start a driver
and drop this program on top of it.
- Parse ups.conf and open the state socket for a driver
- Send DUMPALL and enter a select loop
- Parse SETINFOs that change ups.status
- When you get OB LB, shut down
Completely unprivileged upsmon
==============================
upsmon currently retains root in a forked process so it can call the
shutdown command. The only reason it needs root on most systems is that
only privileged users can signal init or send a message on /dev/initctl.
In the case of systems running sysvinit (Slackware, others?), upsmon
could just open /dev/initctl while it has root and then drop it
completely. When it's time to shut down, fire a control structure at
init across the lingering socket and tell it to enter runlevel 0.
This has been shown to work in local tests, but it's not portable. It
could only be offered as an option for those systems which run that
flavor of init. It also needs to be tested to see what happens to
the lingering fd over time, such as when init restarts after an upgrade.
For other systems, there is always the possibility of having a suid
program which does nothing but prod init into starting a shutdown. Lock
down the group access so only upsmon's unprivileged user can access it,
and make that your SHUTDOWNCMD. Then it could drop root completely.
Chrooted upsmon
===============
upsmon could run the network monitoring part in a chroot jail if it had
a pipe to another process running outside for NOTIFY dispatches. Such a
pipe would have to be constructed extremely carefully so an attacker
could not compromise it from the jailed process.
A state machine with a tightly defined sequence could do this safely.
All it has to do is dispatch the UPS name and event type.
[start] [type] [length] <name> [stop]
Monitor program with interpreted language
=========================================
Once in awhile, I get requests for a way to shut down based on the UPS
temperature, or ambient humidity, or at a certain battery charge level,
or any number of things other than an "OB LB" status. It should be
obvious that adding a way to monitor all of that in upsmon would bloat
upsmon for all those people who really don't need anything like that.
A separate program that interprets a list of rules and uses it to
monitor the UPS equipment is the way to solve this. If you have a
condition that needs to be tested, add a rule.
Some of the tools that such a language would need include simple
greater-than/less-than testing (if battery.charge < 20), equivalence
testing (if ups.model = "SMART-UPS 700"), and some way to set and clear
timers.
Due to the expected size and limited audience for such a program, it
might have to be distributed separately.

66
docs/macros.txt Normal file
View file

@ -0,0 +1,66 @@
Desc: NUT-specific autoconf macros
File: macros.txt
Date: 27 December 2006
Auth: Peter Selinger <selinger@users.sourceforge.net>
The following NUT-specific autoconf macros are defined in the m4/
directory.
- Macro: NUT_TYPE_SOCKLEN_T
- Macro: NUT_TYPE_UINT8_T
- Macro: NUT_TYPE_UINT16_T
Check for the corresponding type in the system header files, and
#define a replacement if necessary.
- Macro: NUT_CHECK_LIBGD
- Macro: NUT_CHECK_LIBHAL
- Macro: NUT_CHECK_LIBNEON
- Macro: NUT_CHECK_LIBNETSNMP
- Macro: NUT_CHECK_LIBPOWERMAN
- Macro: NUT_CHECK_LIBSSL
- Macro: NUT_CHECK_LIBUSB
- Macro: NUT_CHECK_LIBWRAP
Determine the compiler flags for the corresponding library. On
success, set nut_have_libxxx="yes" and set LIBXXX_CFLAGS and
LIBXXX_LDFLAGS. On failure, set nut_have_libxxx="no". This macro
can be run multiple times, but will do the checking only once.
Here "xxx" should of course be replaced by the respective library name.
The checks for each library grow organically to compensate for
various bugs in the libraries, pkg-config, etc. This is why we have
a separate macro for each library.
- Macro: NUT_CHECK_IPV6
Check for various features required to compile the IPv6 support.
dnl Check for various features required for IPv6 support. Define a
preprocessor symbol for each individual feature (HAVE_GETADDRINFO,
HAVE_FREEADDRINFO, HAVE_STRUCT_ADDRINFO, HAVE_SOCKADDR_STORAGE,
SOCKADDR_IN6, IN6_ADDR, HAVE_IN6_IS_ADDR_V4MAPPED,
HAVE_AI_ADDRCONFIG). Also set the shell variable nut_have_ipv6=yes
if all the required features are present. Set nut_have_ipv6=no
otherwise.
- Macro: NUT_CHECK_OS
Check for the exact system name and type.
This was only used in the past to determine the packaging rule to be used
through the OS_NAME variable, but may be useful for other purposes in the
future.
- Macro: NUT_REPORT_FEATURE(FEATURE, VALUE)
Schedule a line for the end-of-configuration feature summary. The
FEATURE is a descriptive string such that the sentence "Checking
whether to FEATURE" makes sense, and VALUE describes the decision
taken (typically yes or no). The feature is also reported to the
terminal.
- Macro: NUT_REPORT(FEATURE, VALUE)
Schedule a line for the end-of-configuration feature summary, without
printing anything to the terminal immediately.
- Macro: NUT_PRINT_FEATURE_REPORT
Print out a list of the features that have been reported by
previous NUT_REPORT_FEATURE macro calls.
- Macro: NUT_ARG_WITH(FEATURE, DESCRIPTION, DEFAULT)
Declare a simple --with-FEATURE option with the given DESCRIPTION
and DEFAULT. Sets the variable nut_with_FEATURE.

69
docs/megatec.txt Normal file
View file

@ -0,0 +1,69 @@
Desc: Issues and direction for the megatec driver
File: megatec.txt
Date: 29 March 2006
Auth: Carlos Rodrigues <carlos.efr@mail.telepac.pt>
Overall concept
===============
The "powermust" driver was originally developed to support the Mustek Powermust
series of UPSes, but since there are some other drivers implementing (mostly)
the same protocol, an idea came up to unify all these other drivers under a
renamed version of "powermust": "megatec".
The idea is to support all the hardware previously supported by the other
drivers with a minimum number of special cases. Most of the time this isn't
difficult, as the protocol states that all unknown/unimplemented commands
should be ignored (the commands are simply echoed back).
Target drivers
==============
The following drivers are targeted for "assimilation":
* blazer (1)
* fentonups (1)
* mustek (1)
* esupssmart (1)
* ippon (1)
* sms (1)
* masterguard (3)
(1) megatec already supercedes this driver in functionality.
(2) megatec partially supercedes this driver in functionality, but some
small features are missing (non-critical for normal operation).
(3) megatec partially supercedes this driver in functionality, but some
important features are missing, which means some hardware may not be
supported.
The above status is infered from some testing and from looking at the code
of the drivers. Although I have a high degree of certainty about it, more
testing is needed/welcome.
Notes
=====
The "masterguard" driver seems to be the most problematic: it implements a
"Q3" command (similar to "Q1" but with extra information), and the command
to get information from the UPS is "WH" instead of "I" (with a different
response also).
All drivers cancel the battery tests with "CT". The protocol seems to imply
that the 10 second battery test can't be cancelled (which makes sense).
The beeper can be toggled with "Q", but there doesn't seem to exist a way to
check if it is on or off, which may confuse users when a "beeper.on" command
actually turns it off and vice-versa (maybe some models default to "on", and
others to "off", this may make this command fit better as a blind
"beeper.toggle").
The "sms" driver implements a simple watchdog (send and "SxxRxxx" command to
power cycle the UPS every time the "reset.watchdog" command is called).
There are two battery tests: failure ("T" - 10sec?) and until LOWBATT ("TL").
Moreover, there are some "S.3" or "S.3R0003" commands which fly in the face
of "S05R0003" which the driver also issues (this last one matches all the
other drivers, the first two seem to imply that the UPS also accepts those
format variations to the standard "SxxRxxxx" shutdown+return commands).
--
Carlos Rodrigues

620
docs/new-drivers.txt Normal file
View file

@ -0,0 +1,620 @@
Desc: How to make a new driver to support another UPS
File: new-drivers.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <arnaud.quette@gmail.com>
Smart vs. Contact-closure
=========================
If your UPS only does contact closure readings, then go straight to the
contact-closure.txt document for information on adding support. It's a
lot easier to add a few lines to a header file than it is to create a
whole new driver.
Serial vs. USB vs. SNMP and more
================================
If your UPS connects to your computer via a USB port, then go straight
to the document hid-subdrivers.txt. You can probably add support for
your device by writing a new subdriver to the existing usbhid-ups
driver, which is easier than writing an entire new driver.
Similarly, if your UPS connects to your computer via an SNMP network
card, you can probably add support for your device by writing a new
subdriver to the existing snmp-ups driver, which is easier than writing
an entire new driver.
Overall concept
===============
The basic design of drivers is simple. main.c handles most of the work
for you. You don't have to worry about arguments, config files, or
anything else like that. Your only concern is talking to the hardware
and providing data to the outside world.
Skeleton driver
===============
Familiarize yourself with the design of skel.c in the drivers directory.
It shows a few examples of the functions that main will call to obtain
updated information from the hardware.
Essential structure
===================
upsdrv_info_t
-------------
This structure tracks several description information about the driver:
* name: the driver full name, for banner printing.
* version: the driver's own version. For sub driver information, refer below
to sub_upsdrv_info. This value has the form "X.YZ", and is
published by main as "driver.version.internal".
* authors: the driver's author(s) name. If multiple authors are listed, separate
them with '\n' so that it can be broken up by author if needed.
* status: the driver development status. The following values are allowed:
- DRV_BROKEN: setting this value will cause main to print an error
and exit. This is only used during conversions of the driver core
to keep users from using drivers which have not been converted.
Drivers in this state will be removed from the tree after some
period if they are not fixed.
- DRV_EXPERIMENTAL: set this value if your driver is potentially
broken. This will trigger a warning when it starts so the user
doesn't take it for granted.
- DRV_BETA: this value means that the driver is more stable and
complete. But it is still not recommended for production systems.
- DRV_STABLE: the driver is suitable for production systems, but not
100 % feature complete.
- DRV_COMPLETE: this is the gold level! It implies that 100 % of the
protocol is implemented, and a full QA pass.
* subdrv_info: array of upsdrv_info_t for sub driver(s) information. This
is used for example by usbhid-ups and megatec.
These information are currently used for the startup banner printing and tests.
Essential functions
===================
upsdrv_initups
--------------
Open the port (device_path) and do any low-level things that it may need
to start using that port. If you have to set DTR or RTS on a serial
port, do it here.
Don't do any sort of hardware detection here, since you may be going
into upsdrv_shutdown next.
upsdrv_initinfo
---------------
Try to detect what kind of UPS is out there, if any, assuming that's
possible for your hardware. If there is a way to detect that hardware
and it doesn't appear to be connected, display an error and exit. This
is the last time your driver is allowed to bail out.
This is usually a good place to create variables like ups.mfr,
ups.model, ups.serial, and other "one time only" items.
upsdrv_updateinfo
-----------------
Poll the hardware, and update any variables that you care about
monitoring. Use dstate_setinfo() to store the new values.
Do at most one pass of the variables. You MUST return from this
function or upsd will be unable to read data from your driver. main
will call this function at regular intervals.
Don't spent more than a couple of seconds in this function. Typically
five (5) seconds is the maximum time allowed before you risk that the
server declares the driver stale. If your UPS hardware requires a
timeout period of several seconds before it answers, consider returning
from this function after sending a command immediately and read the
answer the next time it is called.
You must never abort from upsdrv_updateinfo(), even when the UPS doesn't
seem to be attached anymore. If the connection with the UPS is lost, the
driver should retry to re-establish communication for as long as it is
running. Calling exit() or any of the fatal*() functions is specifically
not allowed anymore.
upsdrv_shutdown
---------------
Do whatever you can to make the UPS power off the load but also return
after the power comes back on. You may use a different command that
keeps the UPS off if the user has requested that with a configuration
setting.
You should attempt the UPS shutdown command even if the UPS detection
fails. If the UPS does not shut down the load, then the user is
vulnerable to a race if the power comes back on during the shutdown
process.
Data types
==========
To be of any use, you must supply data in ups.status. That is the
minimum needed to let upsmon do its job. Whenever possible, you should
also provide anything else that can be monitored by the driver. Some
obvious things are the manufacturer name and model name, voltage data,
and so on.
If you can't figure out some value automatically, use the ups.conf
options to let the user tell you. This can be useful when a driver
needs to support many similar hardware models but can't probe to see
what is actually attached.
Manipulating the data
=====================
All status data lives in structures that are managed by the dstate
functions. All access and modifications must happen through those
functions. Any other changes are forbidden, as they will not pushed out
as updates to things like upsd.
Adding variables
----------------
dstate_setinfo("ups.model", "Mega-Zapper 1500");
Many of these functions take format strings, so you can build the new
values right there:
dstate_setinfo("ups.model", "Mega-Zapper %d", rating);
Setting flags
-------------
Some variables have special properties. They can be writable, and some
are strings. The ST_FLAG_* values can be used to tell upsd more about
what it can do.
dstate_setflags("input.transfer.high", ST_FLAG_RW);
Status data
===========
UPS status flags like on line (OL) and on battery (OB) live in
ups.status. Don't manipulate this by hand. There are functions which
will do this for you.
status_init() - before doing anything else
status_set(val) - add a status word (OB, OL, etc)
status_commit() - push out the update
Possible values for status_set:
OL - On line (mains is present)
OB - On battery (mains is not present)
LB - Low battery
RB - The battery needs to be replaced
CHRG - The battery is charging
DISCHRG - The battery is discharging (inverter is providing load power)
BYPASS - UPS bypass circuit is active - no battery protection is available
CAL - UPS is currently performing runtime calibration (on battery)
OFF - UPS is offline and is not supplying power to the load
OVER - UPS is overloaded
TRIM - UPS is trimming incoming voltage (called "buck" in some hardware)
BOOST - UPS is boosting incoming voltage
Anything else will not be recognized by the usual clients. Coordinate
with me before creating something new, since there will be duplication
and ugliness otherwise.
Note: upsd injects "FSD" by itself following that command by a master
upsmon process. Drivers must not set that value.
Note: the OL and OB flags are an indication of the input line status only.
UPS alarms
==========
These work like ups.status, and have three special functions which you
must use to manage them.
alarm_init() - before doing anything else
alarm_set() - add an alarm word
alarm_commit() - push the value into ups.alarm
Note: the ALARM flag in ups.status is automatically set whenever you use
alarm_set. To remove that flag from ups.status, call alarm_init and
alarm_commit without calling alarm_set in the middle.
You should never try to set or unset the ALARM flag manually.
If you use UPS alarms, the call to status_commit() should be after
alarm_commit(), otherwise there will be a delay in setting the ALARM
flag in ups.status.
There is no official list of alarm words as of this writing, so don't
use these functions until you check with the upsdev list.
Staleness control
=================
If you're not talking to a polled UPS, then you must ensure that it
is still out there and is alive before calling dstate_dataok(). Even
if nothing is changing, you should still "ping" it or do something
else to ensure that it is really available. If the attempts to
contact the UPS fail, you must call dstate_datastale() to inform the
server and clients.
- dstate_dataok()
You must call this if polls are succeeding. A good place to call this
is the bottom of upsdrv_updateinfo().
- dstate_datastale()
You must call this if your status is unusable. A good technique is
to call this before exiting prematurely from upsdrv_updateinfo().
Don't hide calls to these functions deep inside helper functions. It is
very hard to find the origin of staleness warnings, if you call these from
various places in your code. Basically, don't call them from any other
function than from within upsdrv_updateinfo(). There is no need to call
either of these regularly as was stated in previous versions of this
document (that requirement has long gone).
Serial port handling
====================
Drivers which use serial port functions should include serial.h and use
these functions whenever possible:
- int ser_open(const char *port)
This opens the port and locks it if possible, using one of fcntl, lockf,
or uu_lock depending on what may be available. If something fails, it
calls fatal for you. If it succeeds, it always returns the fd that was
opened.
- int ser_set_speed(int fd, const char *port, speed_t speed)
This sets the speed of the port and also does some basic configuring
with tcgetattr and tcsetattr. If you have a special serial
configuration (other than 8N1), then this may not be what you want.
The port name is provided again here so failures in tcgetattr() provide
a useful error message. This is the only place that will generate a
message if someone passes a non-serial port /dev entry to your driver,
so it needs the extra detail.
- int ser_set_dtr(int fd, int state)
- int ser_set_rts(int fd, int state)
These functions can be used to set the modem control lines to provide
cable power on the RS232 interface. Use state = 0 to set the line to 0
and any other value to set it to 1.
- int set_get_dsr(int fd)
- int ser_get_cts(int fd)
- int set_get_dcd(int fd)
These functions read the state of the modem control lines. They will
return 0 if the line is logic 0 and a non-zero value if the line is
logic 1.
- int ser_close(int fd, const char *port)
This function unlocks the port if possible and closes the fd. You
should call this in your upsdrv_cleanup handler.
- int ser_send_char(int fd, char ch)
This attempts to write one character and returns the return value from
write. You could call write directly, but using this function allows
for future error handling in one place.
- int ser_send_pace(int fd, unsigned long d_usec,
const char *fmt, ...)
If you need to send a formatted buffer with an intercharacter delay, use
this function. There are a number of UPS controllers which can't take
commands at the full speed that would normally be possible at a given
bit rate. Adding a small delay usually turns a flaky UPS into a solid
one.
The return value is the number of characters that was sent to the port,
or -1 if something failed.
- int ser_send(int fd, const char *fmt, ...)
Like ser_send_pace, but without a delay. Only use this if you're sure
that your UPS can handle characters at the full line rate.
- int ser_send_buf(int fd, const char *buf, size_t buflen)
This sends a raw buffer to the fd. It is typically used for binary
transmissions. It returns the results of the call to write.
- int ser_send_buf_pace(int fd, unsigned long d_usec, const char *buf,
size_t buflen)
This is just ser_send_buf with an intercharacter delay.
- int ser_get_char(int fd, char *ch, long d_sec, long d_usec)
This will wait up to d_sec seconds + d_usec microseconds for one
character to arrive, storing it at ch. It returns 1 on success, -1
if something fails and 0 on a timeout.
Note: the delay value must not be too large, or your driver will not get
back to the usual idle loop in main in time to answer the PINGs from
upsd. That will cause an oscillation between staleness and normal
behavior.
- int ser_get_buf(int fd, char *buf, size_t buflen, long d_sec,
long d_usec)
Like ser_get_char, but this one reads up to buflen bytes storing all of
them in buf. The buffer is zeroed regardless of success or failure. It
returns the number of bytes read, -1 on failure and 0 on a timeout.
This is essentially a single read() function with a timeout.
- int ser_get_buf_len(int fd, char *buf, size_t buflen, long d_sec,
long d_usec)
Like ser_get_buf, but this one waits for buflen bytes to arrive,
storing all of them in buf. The buffer is zeroed regardless of success
or failure. It returns the number of bytes read, -1 on failure
and 0 on a timeout.
This should only be used for binary reads. See ser_get_line for
protocols that are terminated by characters like CR or LF.
- int ser_get_line(int fd, char *buf, size_t buflen, char endchar,
const char *ignset, long d_sec, long d_usec)
This is the reading function you should use if your UPS tends to send
responses like "OK\r" or "1234\n". It reads up to buflen bytes and
stores them in buf, but it will return immediately if it encounters
endchar. The endchar will not be stored in the buffer. It will also
return if it manages to collect a full buffer before reaching the
endchar. It returns the number of bytes stored in the buffer, -1 on
failure and 0 on a timeout.
If the character matches the ignset with strchr(), it will not be added
to the buffer. If you don't need to ignore any characters, just pass it
an empty string - "".
The buffer is always cleared and is always null-terminated. It does
this by reading at most (buflen - 1) bytes.
Note: any other data which is read after the endchar in the serial
buffer will be lost forever. As a result, you should not use this
unless your UPS uses a polled protocol.
Let's say your endchar is \n and your UPS sends "OK\n1234\nabcd\n".
This function will read() all of that, find the first \n, and stop
there. Your driver will get "OK", and the rest is gone forever.
This also means that you should not "pipeline" commands to the UPS.
Send a query, then read the response, then send the next query.
- int ser_get_line_alert(int fd, char *buf, size_t buflen,
char endchar, const char *ignset, const char *alertset,
void handler(char ch), long d_sec, long d_usec)
This is just like ser_get_line, but it allows you to specify a set of
alert characters which may be received at any time. They are not added
to the buffer, and this function will call your handler function,
passing the character as an argument.
Implementation note: this function actually does all of the work, and
ser_get_line is just a wrapper that sets an empty alertset and a NULL
handler.
- int ser_flush_in(int fd, const char *ignset, int verbose)
This function will drain the input buffer. If verbose is set to a
positive number, then it will announce the characters which have been
read in the syslog. You should not set verbose unless debugging is
enabled, since it could be very noisy.
This function returns the number of characters which were read, so you
can check for extra bytes by looking for a nonzero return value. Zero
will also be returned if the read fails for some reason.
- int set_flush_io(int fd)
This function drains both the in- and output buffers. Return zero on
success.
- void ser_comm_fail(const char *fmt, ...)
Call this whenever your serial communications fail for some reason. It
takes a format string, so you can use variables and other things to
clarify the error. This function does built-in rate-limiting so you
can't spam the syslog.
By default, it will write 10 messages, then it will stop and only write
1 in 100. This allows the driver to keep calling this function while
the problem persists without filling the logs too quickly.
In the old days, drivers would report a failure once, and then would be
silent until things were fixed again. Users had to figure out what was
happening by finding that single error message, or by looking at the
repeated complaints from upsd or the clients.
If your UPS frequently fails to acknowledge polls and this is a known
situation, you should make a couple of attempts before calling this
function.
Note: this does not call dstate_datastale. You still need to do that.
- void ser_comm_good(void)
This will clear the error counter and write a "re-established" message
to the syslog after communications have been lost. Your driver should
call this whenever it has successfully contacted the UPS. A good place
for most drivers is where it calls dstate_dataok.
USB port handling
=================
Drivers which use USB functions should include usb-common.h and use these:
* structure and macro:
You should us the usb_device_id structure, and the USB_DEVICE macro to
declare the supported devices. This allows the automatic extraction of
USB information, to generate the HAL, Hotplug and udev support files.
For example:
/* SomeVendor name */
#define SOMEVENDOR_VENDORID 0xXXXX
/* USB IDs device table */
static usb_device_id sv_usb_device_table [] = {
/* some models 1 */
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xYYYY), NULL },
/* various models */
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xZZZZ), NULL },
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xAAAA), NULL },
/* Terminating entry */
{ -1, -1, NULL }
};
* function:
- is_usb_device_supported(usb_device_id **usb_device_id_list,
int dev_VendorID, int dev_ProductID)
Call this in your device opening / matching function. Pass your usb_device_id
structure, and a set of VendorID / DeviceID.
This function returns one of the following value:
NOT_SUPPORTED (0), POSSIBLY_SUPPORTED (1) or SUPPORTED (2)
POSSIBLY_SUPPORTED is returned when the VendorID is matched, but the DeviceID
is unknown.
For implementation examples, refer to the various USB drivers, and search for
the above patterns.
This set of USB helpers is due to expand is the near future...
Variable names
==============
PLEASE don't make up new variables and commands just because you can.
The new dstate functions give us the power to create just about
anything, but that is a privilege and not a right. Imagine the mess
that would happen if every developer decided on their own way to
represent a common status element.
Check new-names.txt first to find the closest fit. If nothing matches,
contact the upsdev list or mail me directly, and we'll figure it out.
Patches which introduce unlisted names may be modified or dropped.
Message passing support
=======================
See commands.txt.
Enumerated types
================
If you have a variable that can have several specific values, it is
enumerated. You should add each one to make it available to the client:
dstate_addenum("input.transfer.low", "92");
dstate_addenum("input.transfer.low", "95");
dstate_addenum("input.transfer.low", "99");
dstate_addenum("input.transfer.low", "105");
Writable strings
================
Strings that may be changed by the client should have the ST_FLAG_STRING
flag set, and a maximum length byte set in the auxdata.
dstate_setinfo("ups.id", "Big UPS");
dstate_setflags("ups.id", ST_FLAG_STRING | ST_FLAG_RW);
dstate_setaux("ups.id", 8);
If the variable is not writable, don't bother with the flags or the
auxiliary data. It won't be used.
Instant commands
================
If your hardware and driver can support a command, register it.
dstate_addcmd("load.on");
Delays and ser_* functions
==========================
The new ser_* functions may perform reads faster than the UPS is able to
respond in some cases. This means that your driver will call select()
and read() numerous times if your UPS responds in bursts. This also
depends on how fast your system is.
You should check your driver with strace or its equivalent on your
system. If the driver is calling read() multiple times, consider adding
a call to usleep before going into the ser_read_* call. That will give
it a chance to accumulate so you get the whole thing with one call to
read without looping back for more.
This is not a request to save CPU time, even though it may do that. The
important part here is making the strace/ktrace output easier to read.
write(4, "Q1\r", 3) = 3
nanosleep({0, 300000000}, NULL) = 0
select(5, [4], NULL, NULL, {3, 0}) = 1 (in [4], left {3, 0})
read(4, "(120.0 084.0 120.0 0 60.0 22.6"..., 64) = 47
Without that delay, that turns into a mess of selects and reads.
The select returns almost instantly, and read gets a tiny chunk of the
data. Add the delay and you get a nice four-line status poll.
Canonical input mode processing
===============================
If your UPS uses '\n' and/or '\r' as endchar, consider the use of
Canonical Input Mode Processing instead of the ser_get_line* functions.
Using a serial port in this mode means that select() will wait until
a full line is received (or times out). This relieves you from waiting
between sending a command and reading the reply. Another benefit is,
that you no longer have to worry about the case that your UPS sends
"OK\n1234\nabcd\n". This will be broken up cleanly in "OK\n", "1234\n"
and "abcd\n" on consecutive reads, without risk of losing data (which
is an often forgotten side effect of the ser_get_line* functions).
Currently an example how this works can be found in the safenet and
upscode2 drivers. The first uses a single '\r' as endchar, while the
latter accepts either '\n', "\n\r" or "\r\n" as line termination. You
can define other termination characters as well, but can't undefine
'\r' and '\n' (so if you need these as data, this is not for you).

574
docs/new-names.txt Normal file
View file

@ -0,0 +1,574 @@
Desc: New command and variable naming scheme
File: new-names.txt
Date: 09 September 2005
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <arnaud.quette@mgeups.com>
*** NOTE *** : When updating this file, also update data/cmdvartab.
This is a dump of the standard variables and command names used in NUT.
Don't use a name with any of the dstate functions unless it exists here.
If you need a new variable or command name, contact the Development Team
first.
Put another way: if you make up a name that's not in this list and it
gets into the tree, and then we come up with a better name later, clients
that use the undocumented variable will break when it is changed.
Note: "opaque" means programs should not attempt to parse the value for
that variable as it may vary greatly from one UPS to the next. These
strings are best handled directly by the user.
Variables
device: General unit information
Note: these data will be redundant with some ups.* information
during a transition period. The ups.* data will then be removed.
+-------------------------------------------------------------------------+
| Name | Description | Typical value |
|-----------------------+---------------------------+---------------------|
| device.model | Device model | BladeUPS |
|-----------------------+---------------------------+---------------------|
| device.mfr | Device manufacturer | Eaton |
|-----------------------+---------------------------+---------------------|
| device.serial | Device serial number | WS9643050926 |
| | (opaque string) | |
|-----------------------+---------------------------+---------------------|
| device.type | Device type (ups, pdu) | ups |
+-------------------------------------------------------------------------+
ups: General unit information
+-------------------------------------------------------------------------+
| Name | Description | Typical value |
|-----------------------+------------------------------+------------------|
| ups.status | UPS status | OL (see |
| | | new-drivers.txt) |
|-----------------------+------------------------------+------------------|
| ups.alarm | UPS alarms | OVERHEAT |
|-----------------------+------------------------------+------------------|
| ups.time | Internal UPS clock time | 12:34 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.date | Internal UPS clock date | 01-02-03 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.model | UPS model | SMART-UPS 700 |
|-----------------------+------------------------------+------------------|
| ups.mfr | UPS manufacturer | APC |
|-----------------------+------------------------------+------------------|
| ups.mfr.date | UPS manufacturing date | 10/17/96 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.serial | UPS serial number (opaque | WS9643050926 |
| | string) | |
|-----------------------+------------------------------+------------------|
| ups.vendorid | Vendor ID for USB devices | 0463 |
|-----------------------+------------------------------+------------------|
| ups.productid | Product ID for USB devices | 0001 |
|-----------------------+------------------------------+------------------|
| ups.firmware | UPS firmware (opaque string) | 50.9.D |
|-----------------------+------------------------------+------------------|
| ups.firmware.aux | Auxiliary device firmware | 4Kx |
|-----------------------+------------------------------+------------------|
| ups.temperature | UPS temperature (degrees C) | 042.7 |
|-----------------------+------------------------------+------------------|
| ups.load | Load on UPS (percent) | 023.4 |
|-----------------------+------------------------------+------------------|
| ups.load.high | Load when UPS | 100 |
| | switches to overload | |
| | condition ("OVER") (percent) | |
|-----------------------+------------------------------+------------------|
| ups.id | UPS system identifier | Sierra |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| | Interval to wait before | |
| ups.delay.start | restarting the load | 0 |
| | (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.delay.reboot | Interval to wait before | 60 |
| | rebooting the UPS (seconds) | |
|-----------------------+------------------------------+------------------|
| | Interval to wait after | |
| ups.delay.shutdown | shutdown with delay command | 20 |
| | (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.start | Time before the load will be | 30 |
| | started (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.reboot | Time before the load will be | 10 |
| | rebooted (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.shutdown | Time before the load will be | 20 |
| | shutdown (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.test.interval | Interval between self tests | 1209600 (two |
| | (seconds) | weeks) |
|-----------------------+------------------------------+------------------|
| ups.test.result | Results of last self test | Bad battery pack |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.display.language | Language to use on front | E |
| | panel (*** opaque) | |
|-----------------------+------------------------------+------------------|
| ups.contacts | UPS external contact sensors | F0 |
| | (*** opaque) | |
|-----------------------+------------------------------+------------------|
| ups.power | Current value of apparent | 500 |
| | power (Volt-Amps) | |
|-----------------------+------------------------------+------------------|
| ups.power.nominal | Nominal value of apparent | 500 |
| | power (Volt-Amps) | |
|-----------------------+------------------------------+------------------|
| ups.realpower | Current value of real | 300 |
| | power (Watts) | |
|-----------------------+------------------------------+------------------|
| ups.realpower.nominal | Nominal value of real | 300 |
| | power (Watts) | |
|-----------------------+------------------------------+------------------|
| ups.beeper.status | UPS beeper status | enabled |
| | (enabled, disabled or muted) | |
|-----------------------+------------------------------+------------------|
| ups.type | UPS type (*** opaque) | offline |
|-----------------------+------------------------------+------------------|
| ups.watchdog.status | UPS watchdog status | disabled |
| | (enabled or disabled) | |
|-----------------------+------------------------------+------------------|
| ups.start.auto | UPS starts when mains is | yes |
| | (re)applied | |
+-----------------------+------------------------------+------------------+
| ups.start.battery | Allow to start UPS from | yes |
| | battery | |
+-----------------------+------------------------------+------------------+
| ups.start.reboot | UPS coldstarts from battery | yes |
| | (enabled or disabled) | |
+-------------------------------------------------------------------------+
input: Incoming line/power information
+------------------------------------------------------------------------+
| Name | Description | Typical value |
|---------------------------+----------------------------+---------------|
| input.voltage | Input voltage | 121.5 |
|---------------------------+----------------------------+---------------|
| input.voltage.maximum | Maximum incoming voltage | 130 |
| | seen | |
|---------------------------+----------------------------+---------------|
| input.voltage.minimum | Minimum incoming voltage | 100 |
| | seen | |
|---------------------------+----------------------------+---------------|
| input.voltage.nominal | Nominal input voltage | 120 |
|---------------------------+----------------------------+---------------|
| input.voltage.extended | Extended input voltage | no |
| | range | |
|---------------------------+----------------------------+---------------|
| input.transfer.reason | Reason for last transfer | T |
| | to battery (*** opaque) | |
|---------------------------+----------------------------+---------------|
| input.transfer.low | Low voltage transfer point | 91 |
|---------------------------+----------------------------+---------------|
| input.transfer.high | High voltage transfer | 132 |
| | point | |
|---------------------------+----------------------------+---------------|
| input.transfer.low.min | smallest settable low | 85 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.low.max | greatest settable low | 95 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.high.min | smallest settable high | 131 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.high.max | greatest settable high | 136 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.sensitivity | Input power sensitivity | H (high) |
|---------------------------+----------------------------+---------------|
| input.quality | Input power quality (*** | FF |
| | opaque) | |
|---------------------------+----------------------------+---------------|
| input.current | Input current (A) | 4.25 |
|---------------------------+----------------------------+---------------|
| input.current.nominal | Nominal input current (A) | 5.0 |
|---------------------------+----------------------------+---------------|
| input.frequency | Input line frequency (Hz) | 60.00 |
|---------------------------+----------------------------+---------------|
| input.frequency.nominal | Nominal input line | 60 |
| | frequency (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.low | Input line frequency low | 47 |
| | (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.high | Input line frequency high | 63 |
| | (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.extended | Extended input frequency | no |
| | range | |
|---------------------------+----------------------------+---------------|
| input.transfer.boost.low | Low voltage boosting | 190 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.boost.high | High voltage boosting | 210 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.trim.low | Low voltage trimming | 230 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.trim.high | High voltage trimming | 240 |
| | transfer point | |
+------------------------------------------------------------------------+
output: Outgoing power/inverter information
+------------------------------------------------------------------------+
| output.voltage | Output voltage (V) | 120.9 |
|-------------------------------+--------------------------------+-------|
| output.voltage.nominal | Nominal output voltage (V) | 120 |
|-------------------------------+--------------------------------+-------|
| output.frequency | Output frequency (Hz) | 59.9 |
|-------------------------------+--------------------------------+-------|
| output.frequency.nominal | Nominal output frequency (Hz) | 60 |
|-------------------------------+--------------------------------+-------|
| output.current | Output current (A) | 4.25 |
|-------------------------------+--------------------------------+-------|
| output.current.nominal | Nominal output current (A) | 5.0 |
+------------------------------------------------------------------------+
Three-phase additions:
----------------------
The additions for three-phase measurements would produce a very long table
due to all the combinations that are possible, so these additions are
broken down to their base components.
PHASE COUNT DETERMINATION:
--------------------------
input.phases (3 for 3phase, absent or 1 for 1phase)
output.phases (as for input.phases)
DOMAINs:
--------
Any input or output is considered a valid DOMAIN.
input (should really be called input.mains, but keep this for compat)
input.bypass
input.servicebypass
output (should really be called output.load, but keep this for compat)
output.bypass
output.inverter
output.servicebypass
SPECIFICATION (SPEC):
-------------------------
Voltage, current, frequency, etc are considered to be a specification of
the measurement.
With this notation, the old 1phase naming scheme becomes DOMAIN.SPEC
Example: input.current
CONTEXT:
--------
When in 3phase mode we need some way to specify the target for most
measurements in more detail, we call this the CONTEXT.
With this notation, the naming scheme becomes DOMAIN.CONTEXT.SPEC when
in 3phase mode.
Example: input.L1.current
Valid CONTEXTs:
---------------
L1-L2 \
L2-L3 \
L3-L1 for voltage measurements
L1-N /
L2-N /
L3-N /
L1 \
L2 for currrent and power measurements
L3 /
N - for current measurement
Valid SPECs:
-----------
Valid with/without context (ie. per phase or aggregated/averaged)
current Current (A)
current.maximum Maximum seen current (A)
current.minimum Minimum seen current (A)
peakcurrent Peak current
voltage Voltage (V)
voltage.nominal Nominal voltage (V)
voltage.maximum Maximum seen voltage (V)
voltage.minimum Minimum seen voltage (V)
power Apparent power (VA)
power.maximum Maximum seen apparent power (VA)
power.minimum Maximum seen apparent power (VA)
power.percent Percentage of apparent power related to maximum load
power.maximum.percent Max seen percentage of apparent power
power.minimum.percent Min seen percentage of apparent power
realpower Real power (W)
powerfactor Power Factor (dimensionless value between 0.00 and 1.00)
Valid without context (ie. aggregation of all phases):
frequency Frequency (Hz)
frequency.nominal Nominal frequency (Hz)
EXAMPLES:
---------
Partial Three phase - Three phase example:
input.phases: 3
input.frequency: 50.0
input.L1.current: 133.0
input.bypass.L1-L2.voltage: 398.3
output.phases: 3
output.L1.power: 35700
output.powerfactor: 0.82
Partial Three phase - One phase example:
input.phases: 3
input.L2.current: 48.2
input.N.current: 3.4
input.L3-L1.voltage: 405.4
input.frequency: 50.1
output.phases: 1
output.current: 244.2
output.voltage: 120
output.frequency.nominal: 60.0
battery: Any battery details
+------------------------------------------------------------------------+
| battery.charge | Battery charge (percent) | 100.0 |
|-------------------------+------------------------------+---------------|
| battery.charge.low | Remaining battery level when | 20 |
| | UPS switches to LB (percent) | |
|-------------------------+------------------------------+---------------|
| battery.charge.restart | Minimum battery level for | 20 |
| | UPS restart after power-off | |
|-------------------------+------------------------------+---------------|
| battery.charge.warning | Battery level when UPS | |
| | switches to "Warning" state | 50 |
| | (percent) | |
|-------------------------+------------------------------+---------------|
| battery.voltage | Battery voltage (V) | 24.84 |
|-------------------------+------------------------------+---------------|
| battery.capacity | Battery capacity (Ah) | 7.2 |
|-------------------------+------------------------------+---------------|
| battery.current | Battery current (A) | 1.19 |
|-------------------------+------------------------------+---------------|
| battery.temperature | Battery temperature (degrees | 050.7 |
| | C) | |
|-------------------------+------------------------------+---------------|
| battery.voltage.nominal | Nominal battery voltage (V) | 024 |
|-------------------------+------------------------------+---------------|
| battery.runtime | Battery runtime (seconds) | 1080 |
|-------------------------+------------------------------+---------------|
| battery.runtime.elapsed | Elapsed battery runtime | 60 |
| | (seconds) | |
|-------------------------+------------------------------+---------------|
| | Remaining battery runtime | |
| battery.runtime.low | when UPS switches to LB | 180 |
| | (seconds) | |
|-------------------------+------------------------------+---------------|
| battery.alarm.threshold | Battery alarm threshold | 0 (immediate) |
|-------------------------+------------------------------+---------------|
| battery.date | Battery change date (opaque | 11/14/00 |
| | string) | |
|-------------------------+------------------------------+---------------|
| battery.mfr.date | Battery manufacturing date | 2005/04/02 |
| | (opaque string) | |
|-------------------------+------------------------------+---------------|
| battery.packs | Number of battery packs | 001 |
|-------------------------+------------------------------+---------------|
| battery.packs.bad | Number of bad battery packs | 000 |
+-------------------------+------------------------------+---------------+
| battery.type | Battery chemistry | PbAc |
| | (opaque string) | |
+-------------------------+------------------------------+---------------+
| battery.protection | Prevent deep discharge of | yes |
| | battery | |
+-------------------------+------------------------------+---------------+
| battery.energysave | Switch off when running on | no |
| | battery and no/low load | |
+------------------------------------------------------------------------+
ambient: Conditions from external probe equipment
+--------------------------------------------------------------------------+
| ambient.temperature | Ambient temperature | 25.40 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.alarm | Temperature alarm | enabled |
| | (enabled/disabled) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.high | Temperature threshold high | 40 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.low | Temperature threshold low | 5 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.maximum | Maximum temperature seen | 37.6 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.minimum | Minimum temperature seen | 18.1 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity | Ambient relative humidity | 038.8 |
| | (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.alarm | Relative humidity alarm | enabled |
| | (enabled/disabled) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.high | Relative humidity | 80 |
| | threshold high (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.low | Relative humidity | 10 |
| | threshold high (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.maximum | Maximum relative humidity | 60 |
| | seen (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.minimum | Minimum relative humidity | 13 |
| | seen (percent) | |
+--------------------------------------------------------------------------+
outlet: Smart outlet management (smart on/off switch, ...)
+------------------------------------------------------------------------+
| | Outlet system | |
| outlet.n.id | identifier (opaque | 1 |
| | string) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.desc | Outlet description | Main outlet |
| | (opaque string) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.switch | Outlet switch control | on |
| | (on/off) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.status | Outlet switch status | on |
| | (on/off) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.switchable | Outlet switch ability | yes |
| | (yes/no) | |
|--------------------------------+-------------------------+-------------|
| | Remaining battery level | |
| outlet.n.autoswitch.charge.low | to power off this | 90 |
| | outlet (percent) | |
|--------------------------------+-------------------------+-------------|
| | Interval to wait before | |
| outlet.n.delay.shutdown | shutting down this | 180 |
| | outlet (seconds) | |
|--------------------------------+-------------------------+-------------|
| | Interval to wait before | |
| outlet.n.delay.start | restarting this outlet | 120 |
| | (seconds) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.current | Current (A) | 0.19 |
|--------------------------------+-------------------------+-------------|
| outlet.n.current.maximum | Maximum seen current | 0.56 |
| | (A) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.realpower | Current value of real | 28 |
| | power (W) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.voltage | Voltage (V) | 247.0 |
|--------------------------------+-------------------------+-------------|
| | Power Factor | |
| outlet.n.powerfactor | (dimensionless value | 0.85 |
| | between 0 and 1) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.power | Apparent power (VA) | 46 |
+------------------------------------------------------------------------+
driver: Internal driver information
+------------------------------------------------------------------------+
| driver.name | Driver name | apcsmart |
|-------------------------+----------------------------+-----------------|
| driver.version | Driver version (NUT | X.Y.Z |
| | release) | |
|-------------------------+----------------------------+-----------------|
| driver.version.internal | Internal driver version | 1.23.45 |
| | (if tracked separately) | |
|-------------------------+----------------------------+-----------------|
| driver.parameter.xxx | Parameter xxx (ups.conf or | (varies) |
| | cmdline -x) setting | |
|-------------------------+----------------------------+-----------------|
| driver.flag.xxx | Flag xxx (ups.conf or | enabled (or not |
| | cmdline -x) status | present) |
+------------------------------------------------------------------------+
server: Internal server information
+------------------------------------------------------------------------+
| server.info | Server | Network UPS Tools upsd vX.Y.Z - |
| | information | http://www.networkupstools.org/ |
|----------------+----------------+--------------------------------------|
| server.version | Server version | X.Y.Z |
+------------------------------------------------------------------------+
Instant commands
+------------------------------------------------------------------------+
| Name | Description |
|--------------------------+---------------------------------------------|
| load.off | Turn off the load immediately |
|--------------------------+---------------------------------------------|
| load.on | Turn on the load immediately |
|--------------------------+---------------------------------------------|
| shutdown.return | Turn off the load possibly after a delay |
| | and return when power is back |
|--------------------------+---------------------------------------------|
| shutdown.stayoff | Turn off the load possibly after a delay |
| | and remain off even if power returns |
|--------------------------+---------------------------------------------|
| shutdown.stop | Stop a shutdown in progress |
|--------------------------+---------------------------------------------|
| shutdown.reboot | Shut down the load briefly while rebooting |
| | the UPS |
|--------------------------+---------------------------------------------|
| shutdown.reboot.graceful | After a delay, shut down the load briefly |
| | while rebooting the UPS |
|--------------------------+---------------------------------------------|
| test.panel.start | Start testing the UPS panel |
|--------------------------+---------------------------------------------|
| test.panel.stop | Stop a UPS panel test |
|--------------------------+---------------------------------------------|
| test.failure.start | Start a simulated power failure |
|--------------------------+---------------------------------------------|
| test.failure.stop | Stop simulating a power failure |
|--------------------------+---------------------------------------------|
| test.battery.start | Start a battery test |
|--------------------------+---------------------------------------------|
| test.battery.start.quick | Start a "quick" battery test |
|--------------------------+---------------------------------------------|
| test.battery.start.deep | Start a "deep" battery test |
|--------------------------+---------------------------------------------|
| test.battery.stop | Stop the battery test |
|--------------------------+---------------------------------------------|
| calibrate.start | Start runtime calibration |
|--------------------------+---------------------------------------------|
| calibrate.stop | Stop runtime calibration |
|--------------------------+---------------------------------------------|
| bypass.start | Put the UPS in bypass mode |
|--------------------------+---------------------------------------------|
| bypass.stop | Take the UPS out of bypass mode |
|--------------------------+---------------------------------------------|
| reset.input.minmax | Reset minimum and maximum input voltage |
| | status |
|--------------------------+---------------------------------------------|
| reset.watchdog | Reset watchdog timer (forced reboot of |
| | load) |
|--------------------------+---------------------------------------------|
| beeper.enable | Enable UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.disable | Disable UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.mute | Temporarily mute UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.toggle | Toggle UPS beeper/buzzer |
+------------------------------------------------------------------------+

118
docs/nut-hal.txt Normal file
View file

@ -0,0 +1,118 @@
Desc: NUT integration with FreeDesktop HAL - Hardware Abstraction Layer
File: nut-hal.txt
Date: 05 March 2008
Auth: Arnaud Quette <aquette.dev@gmail.com>
This document introduces NUT integration with FreeDesktop HAL
(Hardware Abstraction Layer), also called Integrated Power Management (IPM).
Introduction
------------
This feature, also known as the Common Power Management integration,
allows NUT drivers to feed the HAL system, which will itself feeds
applications such as the Gnome Power Manager, in charge of the
system protection and notification.
This allows a better integration with the HAL supported systems
(Linux, *BSD and Solaris), and to reuse applications that have
been written to support laptop batteries. This also means that
we avoid the code / application redundancy by not using the upsd
and upsmon / NUT Client layer.
Since the NUT driver subset is limited to USB only, at least for
the moment, this should allow this feature to be shipped with a
base system.
From a user point of view, since all the needed components are
present on the system, we can achieve a full plug and play system.
That is to say when you plug your USB UPS, the needed driver is
automatically loaded and the according application (ie GPM) is
made available (displayed) at runtime without having to install
anything else than the base system. Nothing more to install,
nothing more to configure...
Detailed usage
---------------
Since this feature is still a work in progress, the below information
details how to get, install and test it.
Note that the minimum HAL version required is 0.5.8
* install libhal-dev and its dependencies (libdbus-dev)
or equivalent packages for your system.
* "./configure --with-hal && make" from within the nut dir
* either do a "make install" or simply copy the file
drivers/hald-addon* to the HAL addons directory (ie
/usr/lib/hal/ on Debian) or equivalent dir.
* copy the scripts/hal/20-ups-nut-device.fdi file to
$datadir/hal/fdi/information/20thirdparty
for example on Debian: /usr/share/hal/fdi/information/20thirdparty/
* create the (nut user and) group for the udev rule:
addgroup --quiet --system nut
* add the hal user (ex: haldaemon) to the nut group using:
adduser --quiet haldaemon nut
* restart HAL (ie using "/etc/init.d/dbus restart").
I've personaly used "killall hal" and restarted it using
"hald --daemon=no --verbose=yes" to see the verbose logs
* plug your UPS' USB cord into your computer
* you should now see the UPS using:
- [kde-]hal-device-manager,
- gnome power manager (standard applet for battery management), which
will pop up and state that there is an UPS
- ...
Packaging information
---------------------
The HAL support in NUT must currently be packaged separatly (ie in a
specific nut-hal package) and must conflict with the classic nut packages.
This is in order to:
- allow shipping of the HAL support only in the base system,
without including all the NUT drivers and software,
- prevent the NUT HAL addons to get an exclusive
and automatic access on a device, when a user only want to use the
USB support with a classic NUT installation.
This will be addressed when the new NUT configuration framework
will be merged in the main code branch.
Developing information
----------------------
As of NUT 2.2.2, the HAL integration also provide a DBus interface to
allow the calling of two method:
- Shutdown
- SetBeeper (boolean)
Example:
dbus-send --system --print-reply --dest=org.freedesktop.Hal \
/org/freedesktop/Hal/devices/usb_device_463_ffff_1H2E300AH \
org.freedesktop.Hal.Device.UPS.Shutdown
For development purposes, you might want to set the environment variable
"NUT_HAL_DEBUG" to something between "1" and "5". This matches the NUT debug
levels (-DDDDD).
Credits
-------
Thanks to the following people who made this possible:
- David Zeuthen, HAL Project Leader,
- Richard Hughes, Gnome Power Manager Developer.
References
----------
* FreeDesktop HAL: http://freedesktop.org/wiki/Software_2fhal
* Gnome Power Manager: http://www.gnome.org/projects/gnome-power-manager/

86
docs/osd-notify.txt Normal file
View file

@ -0,0 +1,86 @@
Desc: Using upsmon to make On Screen Display (OSD) notification
File: osd-notify.txt
Date: 12 April 2003
Auth: Arnaud Quette <arnaud.quette@free.fr>
This document presents how to display NUT notification using
an On Screen Display (OSD) system.
It is a complement to Russell Kroll's pager.txt, which
can be found on NUT website, or in NUT source tree. Have
a look at this document before reading more.
Pre requisites
--------------
You must have a running NUT installation (driver, upsd and upsmon).
Refer, if necessary, to NUT documentation for installing
and configuring those.
You also need X OSD to be installed. You can either:
- get it on: http://www.ignavus.net/software.html
- Debian: apt-get install xosd-bin
- Mandrake: urpmi xosd
- Others RPM based: get and install xosd (for example, from
http://rpmfind.net/linux/rpm2html/search.php)
Creating osd-notify shell script
--------------------------------
X OSD provides a really nice program, called osd_cat.
For more information on osd_cat, look at its manpage.
For convenience, I've written a small script called
osd-notify which should be available with the present
file.
You can adjust osd-notify settings to match your needs.
In particular, you must put a valid font in "FONT".
Use xfontsel to find one.
Configuring upsmon to use osd-notify
------------------------------------
1) You need to set EXEC flags on the event you want to
be osd-displayed in upsmon.conf. For example
NOTIFYFLAG ONBATT EXEC
NOTIFYFLAG ONLINE EXEC
You can of course set other actions, like WALL or SYSLOG,
and other events. Look at upsmon.conf manual page.
2) Copy osd-notify somewhere on your system (/usr/local/bin
or whatever).
3) Test osd-notify script by calling:
$> osd-notify NUT
4) Tell upsmon where your script is
NOTIFYCMD /path/to/osd-notify
Show time
---------
You need to adjust X11 access right to allow upsmon's
user to display OSD notification on your screen. This
is done with, from within a xterm, by using:
$> xhost +local:nutmon
Don't forget to adjust upsmon's user name according to
your system settings. This must match the value of the
"RUN_AS_USER" field in upsmon.conf
Now, restart upsmon, pull the plug, and see what happens...
For screenshots, have a look at X OSD website:
http://www.ignavus.net/software.html
Conclusion
----------
What great things we can do with a small nut ;-)
Feel free to send me your comments and enhancements.

68
docs/pager.txt Normal file
View file

@ -0,0 +1,68 @@
Desc: Using upsmon and your pager together
File: pager.txt
Date: 28 May 2001
Auth: Russell Kroll <rkroll@exploits.org>
upsmon can call out to a helper script or program when the UPS changes
state. The example upsmon.conf has a full list of which state changes
are available - ONLINE, ONBATT, LOWBATT, and more.
The simple approach
-------------------
- Set EXEC flags on various things in upsmon.conf
NOTIFYFLAG ONBATT EXEC
NOTIFYFLAG ONLINE EXEC
If you want other things like WALL or SYSLOG to happen, just add them.
NOTIFYFLAG ONBATT EXEC+WALL+SYSLOG
You get the idea.
- Tell upsmon where your script is
NOTIFYCMD /path/to/my/script
- Make a simple script like this at that location:
#! /bin/bash
echo "$*" | sendmail -F"ups@mybox" bofh@pager.example.com
- Restart upsmon, pull the plug, and see what happens.
That approach is bare-bones, but you should get the text content of the
alert in the body of the message, since upsmon passes the alert text
(from NOTIFYMSG) as an argument.
This will send mail every time something happens which may become annoying
rather quickly, especially for simple power fluctuations. To only send
messages after some interval, see the upssched.txt file for information
on offset events.
Using more advanced features
----------------------------
Your helper script will be run with a few environment variables set.
UPSNAME - the name of the system that generated the change.
This will be one of your identifiers from the MONITOR
lines in upsmon.conf.
NOTIFYTYPE - this will be ONLINE, ONBATT, or whatever event took
place which made upsmon call your script.
You can use these to do different things based on which system has
changed state. You could have it only send pages for an important
system while totally ignoring a known trouble spot, for example.
Suppressing notify storms
-------------------------
upsmon will call your script every time an event happens that has the
EXEC flag set. This means a quick power failure that lasts mere seconds
might generate several pages in a row. To suppress this sort of
annoyance, use upssched as your NOTIFYCMD program, and configure it to
send pages after a timer has elapsed. See upssched.txt for more
information.

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