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

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;