new upstream 2.8.0

This commit is contained in:
lagertonne 2022-06-29 12:37:36 +02:00
parent fc7f4b43c1
commit b2b0c9995a
836 changed files with 137090 additions and 30018 deletions

View file

@ -1,7 +1,19 @@
# Network UPS Tools: clients
EXTRA_DIST =
# nutclient.cpp for some legacy reason (maybe initial detached development?)
# optionally includes "common.h" with the NUT build setup - and this option
# was never triggered in fact, not until pushed through command line like this:
AM_CXXFLAGS = -DHAVE_NUTCOMMON=1 -I$(top_srcdir)/include
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
$(top_builddir)/common/libcommon.la \
$(top_builddir)/common/libcommonclient.la \
$(top_builddir)/common/libparseconf.la: dummy
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
# by default, link programs in this directory with libcommon.a
LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS)
LDADD = $(top_builddir)/common/libcommon.la libupsclient.la $(NETLIBS)
if WITH_SSL
LDADD += $(LIBSSL_LIBS)
endif
@ -20,9 +32,13 @@ endif
bin_PROGRAMS = upsc upslog upsrw upscmd
dist_bin_SCRIPTS = upssched-cmd
sbin_PROGRAMS = upsmon upssched
lib_LTLIBRARIES = libupsclient.la libnutclient.la
lib_LTLIBRARIES = libupsclient.la
if HAVE_CXX11
lib_LTLIBRARIES += libnutclient.la
lib_LTLIBRARIES += libnutclientstub.la
endif
if WITH_DEV
include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h
include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h nutclientmem.h
endif
if WITH_CGI
cgiexec_PROGRAMS = upsstats.cgi upsimage.cgi upsset.cgi
@ -35,7 +51,7 @@ upslog_SOURCES = upslog.c upsclient.h upslog.h
upsmon_SOURCES = upsmon.c upsmon.h upsclient.h
upssched_SOURCES = upssched.c upssched.h
upssched_LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS)
upssched_LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la $(NETLIBS)
upsimage_cgi_SOURCES = upsimage.c upsclient.h upsimagearg.h cgilib.c cgilib.h
upsimage_cgi_LDADD = $(LDADD) $(LIBGD_LDFLAGS)
@ -46,15 +62,44 @@ upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libcommonclient.la
libupsclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la
if WITH_SSL
libupsclient_la_LIBADD += $(LIBSSL_LIBS)
endif
# libupsclient version information
# Below we set API versions of public libraries
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
libupsclient_la_LDFLAGS = -version-info 4:0:0
# Note that changes here may have to be reflected in packaging (the shared
# object .so names would differ)
# libupsclient version information
libupsclient_la_LDFLAGS = -version-info 6:0:0 -export-symbols-regex ^upscli_
if HAVE_CXX11
# libnutclient version information and build
libnutclient_la_SOURCES = nutclient.h nutclient.cpp
libnutclient_la_LDFLAGS = -version-info 0:0:0
libnutclient_la_LDFLAGS = -version-info 2:0:0
# Needed in not-standalone builds with -DHAVE_NUTCOMMON=1
# which is defined for in-tree CXX builds above:
libnutclient_la_LIBADD = $(top_builddir)/common/libcommonclient.la
else
EXTRA_DIST += nutclient.h nutclient.cpp
endif
if HAVE_CXX11
# libnutclientstub version information and build
libnutclientstub_la_SOURCES = nutclientmem.h nutclientmem.cpp
libnutclientstub_la_LDFLAGS = -version-info 1:0:0
libnutclientstub_la_LIBADD = libnutclient.la
else
EXTRA_DIST += nutclientmem.h nutclientmem.cpp
endif
dummy:
MAINTAINERCLEANFILES = Makefile.in .dirstamp
# NOTE: Do not clean ".deps" in SUBDIRS of the main project,
# the root Makefile.am takes care of that!
#clean-local:
# rm -rf $(builddir)/.deps

View file

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

View file

@ -46,9 +46,12 @@ static char *unescape(char *buf)
hex[1] = buf[++i];
hex[2] = '\0';
if (!isxdigit((unsigned char) hex[0])
|| !isxdigit((unsigned char) hex[0]))
|| !isxdigit((unsigned char) hex[1]))
fatalx(EXIT_FAILURE, "bad escape char");
ch = strtol(hex, NULL, 16);
long l = strtol(hex, NULL, 16);
assert(l>=0);
assert(l<=255);
ch = (char)l; /* FIXME: Loophole about non-ASCII symbols in top 128 values, or negatives for signed char... */
if ((ch == 10) || (ch == 13))
ch = ' ';
@ -89,7 +92,7 @@ void extractcgiargs(void)
continue;
}
*eq = '\0';
value = eq + 1;
amp = strchr(value, '&');
@ -101,7 +104,7 @@ void extractcgiargs(void)
ptr = NULL;
cleanvar = unescape(varname);
cleanval = unescape(value);
cleanval = unescape(value);
parsearg(cleanvar, cleanval);
free(cleanvar);
free(cleanval);
@ -199,4 +202,4 @@ int checkhost(const char *host, char **desc)
pconf_finish(&ctx);
return 0; /* not found: access denied */
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

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

252
clients/nutclientmem.cpp Normal file
View file

@ -0,0 +1,252 @@
/* nutclientmem.cpp - nutclientmem C++ library implementation
Copyright (C) 2021 Eric Clappier <ericclappier@eaton.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "nutclientmem.h"
#include <common.h>
namespace nut
{
/*
*
* Memory Client stub implementation
*
*/
Device MemClientStub::getDevice(const std::string& name)
{
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceNames()
{
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceDescription(const std::string& name)
{
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceVariableNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::set<std::string> MemClientStub::getDeviceRWVariableNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceVariableDescription(const std::string& dev, const std::string& name)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
ListValue MemClientStub::getDeviceVariableValue(const std::string& dev, const std::string& name)
{
ListValue res;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
auto map = it_dev->second;
auto it_map = map.find(name);
if (it_map != map.end())
{
res = it_map->second;
}
}
return res;
}
ListObject MemClientStub::getDeviceVariableValues(const std::string& dev)
{
ListObject res;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
res = it_dev->second;
}
return res;
}
ListDevice MemClientStub::getDevicesVariableValues(const std::set<std::string>& devs)
{
ListDevice res;
for (auto itr = devs.begin(); itr != devs.end(); itr++)
{
std::string dev = *itr;
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
res.insert(std::pair<std::string, ListObject>(dev, it_dev->second));
}
}
return res;
}
TrackingID MemClientStub::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)
{
auto it_dev = _values.find(dev);
if (it_dev == _values.end())
{
ListObject list;
_values.emplace(dev, list);
it_dev = _values.find(dev);
}
if (it_dev != _values.end())
{
auto map = &(it_dev->second);
auto it_map = map->find(name);
if (it_map != map->end())
{
it_map->second[0] = value;
}
else
{
ListValue list_value;
list_value.push_back(value);
map->emplace(name, list_value);
}
}
return "";
}
TrackingID MemClientStub::setDeviceVariable(const std::string& dev, const std::string& name, const ListValue& values)
{
auto it_dev = _values.find(dev);
if (it_dev != _values.end())
{
auto map = &(it_dev->second);
auto it_map = map->find(name);
if (it_map != map->end())
{
it_map->second = values;
}
else
{
map->emplace(name, values);
}
}
return "";
}
std::set<std::string> MemClientStub::getDeviceCommandNames(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
std::string MemClientStub::getDeviceCommandDescription(const std::string& dev, const std::string& name)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
throw NutException("Not implemented");
}
TrackingID MemClientStub::executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param)
{
NUT_UNUSED_VARIABLE(dev);
NUT_UNUSED_VARIABLE(name);
NUT_UNUSED_VARIABLE(param);
throw NutException("Not implemented");
}
void MemClientStub::deviceLogin(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
/* Note: "master" is deprecated, but supported
* for mixing old/new client/server combos: */
void MemClientStub::deviceMaster(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
void MemClientStub::devicePrimary(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
void MemClientStub::deviceForcedShutdown(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
int MemClientStub::deviceGetNumLogins(const std::string& dev)
{
NUT_UNUSED_VARIABLE(dev);
throw NutException("Not implemented");
}
TrackingResult MemClientStub::getTrackingResult(const TrackingID& id)
{
NUT_UNUSED_VARIABLE(id);
throw NutException("Not implemented");
//return TrackingResult::SUCCESS;
}
bool MemClientStub::isFeatureEnabled(const Feature& feature)
{
NUT_UNUSED_VARIABLE(feature);
throw NutException("Not implemented");
}
void MemClientStub::setFeature(const Feature& feature, bool status)
{
NUT_UNUSED_VARIABLE(feature);
NUT_UNUSED_VARIABLE(status);
throw NutException("Not implemented");
}
} /* namespace nut */
/**
* C nutclient API.
*/
extern "C" {
NUTCLIENT_MEM_t nutclient_mem_create_client()
{
nut::MemClientStub* client = new nut::MemClientStub;
try
{
return static_cast<NUTCLIENT_MEM_t>(client);
}
catch(nut::NutException& ex)
{
// TODO really catch it
NUT_UNUSED_VARIABLE(ex);
delete client;
return nullptr;
}
}
} /* extern "C" */

118
clients/nutclientmem.h Normal file
View file

@ -0,0 +1,118 @@
/* nutclientmem.h - definitions for nutclientmem C/C++ library
Copyright (C) 2021 Eric Clappier <ericclappier@eaton.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUTCLIENTMEM_HPP_SEEN
#define NUTCLIENTMEM_HPP_SEEN
/* Begin of C++ nutclient library declaration */
#ifdef __cplusplus
#include "nutclient.h"
namespace nut
{
typedef std::vector<std::string> ListValue;
typedef std::map<std::string, ListValue> ListObject;
typedef std::map<std::string, ListObject> ListDevice;
/**
* Memory client stub.
* Class to stub TCPClient for test (data store in local memory).
*/
class MemClientStub : public Client
{
public:
/**
* Construct a nut MemClientStub object.
*/
MemClientStub() {}
~MemClientStub() override {}
virtual void authenticate(const std::string& user, const std::string& passwd) override {
NUT_UNUSED_VARIABLE(user);
NUT_UNUSED_VARIABLE(passwd);
}
virtual void logout() override {}
virtual Device getDevice(const std::string& name) override;
virtual std::set<std::string> getDeviceNames() override;
virtual std::string getDeviceDescription(const std::string& name) override;
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev) override;
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev) override;
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name) override;
virtual ListValue getDeviceVariableValue(const std::string& dev, const std::string& name) override;
virtual ListObject getDeviceVariableValues(const std::string& dev) override;
virtual ListDevice getDevicesVariableValues(const std::set<std::string>& devs) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value) override;
virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const ListValue& values) override;
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev) override;
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name) override;
virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param="") override;
virtual void deviceLogin(const std::string& dev) override;
/* Note: "master" is deprecated, but supported
* for mixing old/new client/server combos: */
virtual void deviceMaster(const std::string& dev) override;
virtual void devicePrimary(const std::string& dev) override;
virtual void deviceForcedShutdown(const std::string& dev) override;
virtual int deviceGetNumLogins(const std::string& dev) override;
virtual TrackingResult getTrackingResult(const TrackingID& id) override;
virtual bool isFeatureEnabled(const Feature& feature) override;
virtual void setFeature(const Feature& feature, bool status) override;
private:
ListDevice _values;
};
} /* namespace nut */
#endif /* __cplusplus */
/* End of C++ nutclient library declaration */
/* Begin of C nutclient library declaration */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Nut MEM client dedicated types and functions
*/
/**
* Hidden structure representing a MEM connection.
* NUTCLIENT_MEM_t is back compatible to NUTCLIENT_t.
*/
typedef NUTCLIENT_t NUTCLIENT_MEM_t;
/**
* Create a client to NUTD using memory.
* \return New client or nullptr if failed.
*/
NUTCLIENT_MEM_t nutclient_mem_create_client();
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* End of C nutclient library declaration */
#endif /* NUTCLIENTMOCK_HPP_SEEN */

View file

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

View file

@ -1,4 +1,4 @@
/* upsc - simple "client" to test communications
/* upsc - simple "client" to test communications
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
Copyright (C) 2012 Arnaud Quette <arnaud.quette@free.fr>
@ -25,6 +25,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
static char *upsname = NULL, *hostname = NULL;
@ -58,7 +59,7 @@ static void usage(const char *prog)
static void printvar(const char *var)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -86,7 +87,7 @@ static void printvar(const char *var)
}
if (numa < numq) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least %d)", numa, numq);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least %zu)", numa, numq);
}
printf("%s\n", answer[3]);
@ -95,7 +96,7 @@ static void printvar(const char *var)
static void list_vars(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -119,7 +120,7 @@ static void list_vars(void)
/* VAR <upsname> <varname> <val> */
if (numa < 4) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
printf("%s: %s\n", answer[2], answer[3]);
@ -129,7 +130,7 @@ static void list_vars(void)
static void list_upses(int verbose)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -137,7 +138,7 @@ static void list_upses(int verbose)
numq = 1;
ret = upscli_list_start(ups, numq, query);
if (ret < 0) {
/* check for an old upsd */
if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) {
@ -151,7 +152,7 @@ static void list_upses(int verbose)
/* UPS <upsname> <description> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 3)", numa);
}
if(verbose) {
@ -165,7 +166,7 @@ static void list_upses(int verbose)
static void list_clients(const char *devname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -188,7 +189,7 @@ static void list_clients(const char *devname)
/* CLIENT <upsname> <address> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa);
fatalx(EXIT_FAILURE, "Error: insufficient data (got %zu args, need at least 3)", numa);
}
printf("%s\n", answer[2]);
@ -208,7 +209,8 @@ static void clean_exit(void)
int main(int argc, char **argv)
{
int i, port;
int i;
uint16_t port;
int varlist = 0, clientlist = 0, verbose = 0;
const char *prog = xbasename(argv[0]);
@ -218,7 +220,9 @@ int main(int argc, char **argv)
{
case 'L':
verbose = 1;
goto fallthrough_case_l;
case 'l':
fallthrough_case_l:
varlist = 1;
break;
case 'c':
@ -227,6 +231,9 @@ int main(int argc, char **argv)
case 'V':
fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION);
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_SUCCESS); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
case 'h':
default:

View file

@ -25,7 +25,7 @@
#ifdef HAVE_PTHREAD
/* this include is needed on AIX to have errno stored in thread local storage */
#include <pthread.h>
#endif
#endif
#include <errno.h>
#include <netdb.h>
@ -38,13 +38,14 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include "upsclient.h"
#include "common.h"
#include "nut_stdint.h"
#include "timehead.h"
#include "upsclient.h"
/* WA for Solaris/i386 bug: non-blocking connect sets errno to ENOENT */
#if (defined NUT_PLATFORM_SOLARIS && CPU_TYPE == i386)
#define SOLARIS_i386_NBCONNECT_ENOENT(status) (ENOENT == (status))
#if (defined NUT_PLATFORM_SOLARIS)
#define SOLARIS_i386_NBCONNECT_ENOENT(status) ( (!strcmp("i386", CPU_TYPE)) ? (ENOENT == (status)) : 0 )
#else
#define SOLARIS_i386_NBCONNECT_ENOENT(status) (0)
#endif /* end of Solaris/i386 WA for non-blocking connect */
@ -75,7 +76,7 @@
#define shutdown_how 2
#endif
struct {
static struct {
int flags;
const char *str;
} upscli_errlist[] =
@ -131,7 +132,7 @@ typedef struct HOST_CERT_s {
const char *certname;
int certverify;
int forcessl;
struct HOST_CERT_s *next;
} HOST_CERT_t;
static HOST_CERT_t* upscli_find_host_cert(const char* hostname);
@ -153,7 +154,7 @@ static char* nsscertpasswd = NULL;
static void ssl_debug(void)
{
int e;
unsigned long e;
char errmsg[SMALLBUF];
while ((e = ERR_get_error()) != 0) {
@ -162,32 +163,36 @@ static void ssl_debug(void)
}
}
static int ssl_error(SSL *ssl, int ret)
static int ssl_error(SSL *ssl, ssize_t ret)
{
int e;
e = SSL_get_error(ssl, ret);
if (ret >= INT_MAX) {
upslogx(LOG_ERR, "ssl_error() ret=%zd would not fit in an int", ret);
return -1;
}
e = SSL_get_error(ssl, (int)ret);
switch (e)
{
case SSL_ERROR_WANT_READ:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_WANT_READ", ret);
break;
case SSL_ERROR_WANT_WRITE:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_WRITE", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_WANT_WRITE", ret);
break;
case SSL_ERROR_SYSCALL:
if (ret == 0 && ERR_peek_error() == 0) {
upslogx(LOG_ERR, "ssl_error() EOF from client");
} else {
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_SYSCALL", ret);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR_SYSCALL", ret);
}
break;
default:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
upslogx(LOG_ERR, "ssl_error() ret=%zd SSL_ERROR %d", ret, e);
ssl_debug();
}
@ -196,9 +201,12 @@ static int ssl_error(SSL *ssl, int ret)
#elif defined(WITH_NSS) /* WITH_OPENSSL */
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
void *arg)
{
NUT_UNUSED_VARIABLE(retry);
NUT_UNUSED_VARIABLE(arg);
upslogx(LOG_INFO, "Intend to retrieve password for %s / %s: password %sconfigured",
PK11_GetSlotName(slot), PK11_GetTokenName(slot), nsscertpasswd?"":"not ");
return nsscertpasswd ? PL_strdup(nsscertpasswd) : NULL;
@ -233,6 +241,10 @@ static SECStatus AuthCertificateDontVerify(CERTCertDBHandle *arg, PRFileDesc *fd
PRBool checksig, PRBool isServer)
{
UPSCONN_t *ups = (UPSCONN_t *)SSL_RevealPinArg(fd);
NUT_UNUSED_VARIABLE(arg);
NUT_UNUSED_VARIABLE(checksig);
NUT_UNUSED_VARIABLE(isServer);
upslogx(LOG_INFO, "Do not intend to authenticate server %s",
ups?ups->host:"<unnamed>");
return SECSuccess;
@ -241,6 +253,8 @@ static SECStatus AuthCertificateDontVerify(CERTCertDBHandle *arg, PRFileDesc *fd
static SECStatus BadCertHandler(UPSCONN_t *arg, PRFileDesc *fd)
{
HOST_CERT_t* cert;
NUT_UNUSED_VARIABLE(fd);
upslogx(LOG_WARNING, "Certificate validation failed for %s",
(arg&&arg->host)?arg->host:"<unnamed>");
/* BadCertHandler is called when the NSS certificate validation is failed.
@ -288,49 +302,63 @@ static SECStatus GetClientAuthData(UPSCONN_t *arg, PRFileDesc *fd,
static void HandshakeCallback(PRFileDesc *fd, UPSCONN_t *client_data)
{
NUT_UNUSED_VARIABLE(fd);
upslogx(LOG_INFO, "SSL handshake done successfully with server %s",
client_data->host);
}
#endif /* WITH_OPENSSL | WITH_NSS */
int upscli_init(int certverify, const char *certpath,
int upscli_init(int certverify, const char *certpath,
const char *certname, const char *certpasswd)
{
#ifdef WITH_OPENSSL
int ret, ssl_mode = SSL_VERIFY_NONE;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const SSL_METHOD *ssl_method;
#else
SSL_METHOD *ssl_method;
#endif
long ret;
int ssl_mode = SSL_VERIFY_NONE;
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certpasswd);
#elif defined(WITH_NSS) /* WITH_OPENSSL */
SECStatus status;
#else
NUT_UNUSED_VARIABLE(certverify);
NUT_UNUSED_VARIABLE(certpath);
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certpasswd);
#endif /* WITH_OPENSSL | WITH_NSS */
if (upscli_initialized == 1) {
upslogx(LOG_WARNING, "upscli already initialized");
return -1;
}
#ifdef WITH_OPENSSL
SSL_library_init();
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_load_error_strings();
SSL_library_init();
ssl_method = TLSv1_client_method();
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#else
ssl_ctx = SSL_CTX_new(TLS_client_method());
#endif
if (!ssl_method) {
return 0;
}
ssl_ctx = SSL_CTX_new(ssl_method);
if (!ssl_ctx) {
upslogx(LOG_ERR, "Can not initialize SSL context");
return -1;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* set minimum protocol TLSv1 */
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
#else
ret = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
if (ret != 1) {
upslogx(LOG_ERR, "Can not set minimum protocol to TLSv1");
return -1;
}
#endif
if (!certpath) {
if (certverify == 1) {
upslogx(LOG_ERR, "Can not verify certificate if any is specified");
@ -353,13 +381,13 @@ int upscli_init(int certverify, const char *certpath,
return -1;
}
SSL_CTX_set_verify(ssl_ctx, ssl_mode, NULL);
SSL_CTX_set_verify(ssl_ctx, ssl_mode, NULL);
}
#elif defined(WITH_NSS) /* WITH_OPENSSL */
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
PK11_SetPasswordFunc(nss_password_callback);
if (certpath) {
upslogx(LOG_INFO, "Init SSL with cerificate database located at %s", certpath);
status = NSS_Init(certpath);
@ -372,16 +400,16 @@ int upscli_init(int certverify, const char *certpath,
nss_error("upscli_init / NSS_[NoDB]_Init");
return -1;
}
status = NSS_SetDomesticPolicy();
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not initialize SSL policy");
nss_error("upscli_init / NSS_SetDomesticPolicy");
return -1;
}
SSL_ClearSessionCache();
status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not enable SSLv3");
@ -407,8 +435,13 @@ int upscli_init(int certverify, const char *certpath,
nsscertpasswd = xstrdup(certpasswd);
}
verify_certificate = certverify;
#else
/* Note: historically we do not return with error here,
* just fall through to below and treat as initialized.
*/
upslogx(LOG_ERR, "upscli_init called but SSL wasn't compiled in");
#endif /* WITH_OPENSSL | WITH_NSS */
upscli_initialized = 1;
return 1;
}
@ -423,6 +456,11 @@ void upscli_add_host_cert(const char* hostname, const char* certname, int certve
cert->certverify = certverify;
cert->forcessl = forcessl;
first_host_cert = cert;
#else
NUT_UNUSED_VARIABLE(hostname);
NUT_UNUSED_VARIABLE(certname);
NUT_UNUSED_VARIABLE(certverify);
NUT_UNUSED_VARIABLE(forcessl);
#endif /* WITH_NSS */
}
@ -438,11 +476,13 @@ static HOST_CERT_t* upscli_find_host_cert(const char* hostname)
cert = cert->next;
}
}
#else
NUT_UNUSED_VARIABLE(hostname);
#endif /* WITH_NSS */
return NULL;
}
int upscli_cleanup()
int upscli_cleanup(void)
{
#ifdef WITH_OPENSSL
if (ssl_ctx) {
@ -452,7 +492,7 @@ int upscli_cleanup()
#endif /* WITH_OPENSSL */
#ifdef WITH_NSS
#ifdef WITH_NSS
/* Called to force cache clearing to prevent NSS shutdown failures.
* http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1138601
*/
@ -465,7 +505,7 @@ int upscli_cleanup()
*/
PL_ArenaFinish();
#endif /* WITH_NSS */
upscli_initialized = 0;
return 1;
}
@ -477,6 +517,16 @@ const char *upscli_strerror(UPSCONN_t *ups)
char sslbuf[UPSCLI_ERRBUF_LEN];
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
if (!ups) {
return upscli_errlist[UPSCLI_ERR_INVALIDARG].str;
}
@ -517,12 +567,12 @@ const char *upscli_strerror(UPSCONN_t *ups)
if (PR_GetErrorTextLength() < UPSCLI_ERRBUF_LEN) {
PR_GetErrorText(ups->errbuf);
} else {
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
"SSL error #%ld, message too long to be displayed",
(long)PR_GetError());
}
#else
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
"SSL error, but SSL wasn't enabled at compile-time");
#endif /* WITH_OPENSSL | WITH_NSS */
return ups->errbuf;
@ -534,6 +584,10 @@ const char *upscli_strerror(UPSCONN_t *ups)
return ups->errbuf;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
/* fallthrough */
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN, "Unknown error flag %d",
@ -545,9 +599,9 @@ const char *upscli_strerror(UPSCONN_t *ups)
/* Read up to buflen bytes from fd and return the number of bytes
read. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int upscli_select_read(const int fd, void *buf, const size_t buflen, const long d_sec, const long d_usec)
static ssize_t upscli_select_read(const int fd, void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
ssize_t ret;
fd_set fds;
struct timeval tv;
@ -566,17 +620,37 @@ static int upscli_select_read(const int fd, void *buf, const size_t buflen, cons
return read(fd, buf, buflen);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* internal: abstract the SSL calls for the other functions */
static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
static ssize_t net_read(UPSCONN_t *ups, char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret = -1;
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_read(ups->ssl, buf, buflen);
/* SSL_* routines deal with int type for return and buflen
* We might need to window our I/O if we exceed 2GB (in
* 32-bit builds)... Not likely to exceed in 64-bit builds,
* but smaller systems with 16-bits might be endangered :)
*/
assert(buflen <= INT_MAX);
int iret = SSL_read(ups->ssl, buf, (int)buflen);
assert(iret <= SSIZE_MAX);
ret = (ssize_t)iret;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Read(ups->ssl, buf, buflen);
/* PR_* routines deal in PRInt32 type
* We might need to window our I/O if we exceed 2GB :) */
assert(buflen <= PR_INT32_MAX);
ret = PR_Read(ups->ssl, buf, (PRInt32)buflen);
#endif /* WITH_OPENSSL | WITH_NSS*/
if (ret < 1) {
@ -587,7 +661,7 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
}
#endif
ret = upscli_select_read(ups->fd, buf, buflen, 5, 0);
ret = upscli_select_read(ups->fd, buf, buflen, timeout, 0);
/* error reading data, server disconnected? */
if (ret < 0) {
@ -602,13 +676,16 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
return ret;
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
/* Write up to buflen bytes to fd and return the number of bytes
written. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int upscli_select_write(const int fd, const void *buf, const size_t buflen, const long d_sec, const long d_usec)
static ssize_t upscli_select_write(const int fd, const void *buf, const size_t buflen, const time_t d_sec, const suseconds_t d_usec)
{
int ret;
ssize_t ret;
fd_set fds;
struct timeval tv;
@ -627,17 +704,37 @@ static int upscli_select_write(const int fd, const void *buf, const size_t bufle
return write(fd, buf, buflen);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* internal: abstract the SSL calls for the other functions */
static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
static ssize_t net_write(UPSCONN_t *ups, const char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret = -1;
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_write(ups->ssl, buf, buflen);
/* SSL_* routines deal with int type for return and buflen
* We might need to window our I/O if we exceed 2GB (in
* 32-bit builds)... Not likely to exceed in 64-bit builds,
* but smaller systems with 16-bits might be endangered :)
*/
assert(buflen <= INT_MAX);
int iret = SSL_write(ups->ssl, buf, (int)buflen);
assert(iret <= SSIZE_MAX);
ret = (ssize_t)iret;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Write(ups->ssl, buf, buflen);
/* PR_* routines deal in PRInt32 type
* We might need to window our I/O if we exceed 2GB :) */
assert(buflen <= PR_INT32_MAX);
ret = PR_Write(ups->ssl, buf, (PRInt32)buflen);
#endif /* WITH_OPENSSL | WITH_NSS */
if (ret < 1) {
@ -648,7 +745,7 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
}
#endif
ret = upscli_select_write(ups->fd, buf, buflen, 0, 0);
ret = upscli_select_write(ups->fd, buf, buflen, timeout, 0);
/* error writing data, server disconnected? */
if (ret < 0) {
@ -663,6 +760,9 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
return ret;
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
#ifdef WITH_SSL
@ -670,7 +770,7 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
/*
* 1 : OK
* -1 : ERROR
* 0 : SSL NOT SUPPORTED
* 0 : SSL NOT SUPPORTED
*/
static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
{
@ -679,7 +779,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
#elif defined(WITH_NSS) /* WITH_OPENSSL */
SECStatus status;
PRFileDesc *socket;
HOST_CERT_t *cert;
HOST_CERT_t *cert;
#endif /* WITH_OPENSSL | WITH_NSS */
char buf[UPSCLI_NETBUF_LEN];
@ -691,7 +791,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
"force initialisation without SSL configuration");
upscli_init(0, NULL, NULL, NULL);
}
/* see if upsd even talks SSL/TLS */
snprintf(buf, sizeof(buf), "STARTTLS\n");
@ -708,7 +808,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
}
/* upsd is happy, so let's crank up the client */
#ifdef WITH_OPENSSL
if (!ssl_ctx) {
@ -737,7 +837,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
switch(res)
{
case 1:
upsdebugx(3, "SSL connected");
upsdebugx(3, "SSL connected (%s)", SSL_get_version(ups->ssl));
break;
case 0:
upslog_with_errno(1, "SSL_connect do not accept handshake.");
@ -747,7 +847,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
upslog_with_errno(1, "Unknown return value from SSL_connect %d", res);
ssl_error(ups->ssl, res);
return -1;
}
}
return 1;
@ -764,12 +864,12 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
nss_error("upscli_sslinit / SSL_ImportFD");
return -1;
}
if (SSL_SetPKCS11PinArg(ups->ssl, ups) == -1){
nss_error("upscli_sslinit / SSL_SetPKCS11PinArg");
return -1;
}
if (verifycert) {
status = SSL_AuthCertificateHook(ups->ssl,
(SSLAuthCertificate)AuthCertificate, CERT_GetDefaultCertDB());
@ -781,19 +881,19 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
nss_error("upscli_sslinit / SSL_AuthCertificateHook");
return -1;
}
status = SSL_BadCertHook(ups->ssl, (SSLBadCertHandler)BadCertHandler, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_BadCertHook");
return -1;
}
status = SSL_GetClientAuthDataHook(ups->ssl, (SSLGetClientAuthData)GetClientAuthData, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_GetClientAuthDataHook");
return -1;
}
status = SSL_HandshakeCallback(ups->ssl, (SSLHandshakeCallback)HandshakeCallback, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_HandshakeCallback");
@ -830,9 +930,9 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
/* TODO : Close the connection. */
return -1;
}
return 1;
#endif /* WITH_OPENSSL | WITH_NSS */
}
@ -840,12 +940,15 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
{
NUT_UNUSED_VARIABLE(ups);
NUT_UNUSED_VARIABLE(verifycert);
return 0; /* not supported */
}
#endif /* WITH_SSL */
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout)
int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags, struct timeval * timeout)
{
int sock_fd;
struct addrinfo hints, *res, *ai;
@ -871,7 +974,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
return -1;
}
snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port);
snprintf(sport, sizeof(sport), "%ju", (uintmax_t)port);
memset(&hints, 0, sizeof(hints));
@ -1005,7 +1108,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
ups->port = port;
hostcert = upscli_find_host_cert(host);
if (hostcert != NULL) {
/* An host security rule is specified. */
certverify = hostcert->certverify;
@ -1015,39 +1118,39 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
forcessl = (flags & UPSCLI_CONN_REQSSL) != 0 ? 1 : 0;
}
tryssl = (flags & UPSCLI_CONN_TRYSSL) != 0 ? 1 : 0;
if (tryssl || forcessl) {
ret = upscli_sslinit(ups, certverify);
if (forcessl && ret != 1) {
upslogx(LOG_ERR, "Can not connect to %s in SSL, disconnect", host);
upslogx(LOG_ERR, "Can not connect to NUT server %s in SSL, disconnect", host);
ups->upserror = UPSCLI_ERR_SSLFAIL;
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == -1) {
upslogx(LOG_NOTICE, "Error while connecting to %s, disconnect", host);
upslogx(LOG_NOTICE, "Error while connecting to NUT server %s, disconnect", host);
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == 0) {
if (certverify != 0) {
upslogx(LOG_NOTICE, "Can not connect to %s in SSL and "
upslogx(LOG_NOTICE, "Can not connect to NUT server %s in SSL and "
"certificate is needed, disconnect", host);
upscli_disconnect(ups);
return -1;
}
upsdebugx(3, "Can not connect to %s in SSL, continue uncrypted", host);
upsdebugx(3, "Can not connect to NUT server %s in SSL, continue unencrypted", host);
} else {
upslogx(LOG_INFO, "Connected to %s in SSL", host);
upslogx(LOG_INFO, "Connected to NUT server %s in SSL", host);
if (certverify == 0) {
/* you REALLY should set CERTVERIFY to 1 if using SSL... */
upslogx(LOG_WARNING, "Certificate verification is disabled");
}
}
}
return 0;
}
int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags)
int upscli_connect(UPSCONN_t *ups, const char *host, uint16_t port, int flags)
{
return upscli_tryconnect(ups,host,port,flags,NULL);
}
@ -1058,7 +1161,7 @@ static struct {
const char *text;
} upsd_errlist[] =
{
{ UPSCLI_ERR_VARNOTSUPP, "VAR-NOT-SUPPORTED" },
{ UPSCLI_ERR_VARNOTSUPP, "VAR-NOT-SUPPORTED" },
{ UPSCLI_ERR_UNKNOWNUPS, "UNKNOWN-UPS" },
{ UPSCLI_ERR_ACCESSDENIED, "ACCESS-DENIED" },
{ UPSCLI_ERR_PWDREQUIRED, "PASSWORD-REQUIRED" },
@ -1083,7 +1186,7 @@ static struct {
{ UPSCLI_ERR_INVPASSWORD, "INVALID-PASSWORD" },
{ UPSCLI_ERR_USERREQUIRED, "USERNAME-REQUIRED" },
{ UPSCLI_ERR_DRVNOTCONN, "DRIVER-NOT-CONNECTED" },
{ 0, NULL, }
};
@ -1120,9 +1223,9 @@ static int upscli_errcheck(UPSCONN_t *ups, char *buf)
}
static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
int numarg, const char **arg)
size_t numarg, const char **arg)
{
int i;
size_t i;
size_t len;
char enc[UPSCLI_NETBUF_LEN];
const char *format;
@ -1142,8 +1245,20 @@ static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
/* snprintfcat would tie us to common */
len = strlen(buf);
snprintf(buf + len, bufsize - len, format,
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
snprintf(buf + len, bufsize - len, format,
pconf_encode(arg[i], enc, sizeof(enc)));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
len = strlen(buf);
@ -1151,9 +1266,9 @@ static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
}
/* make sure upsd is giving us what we asked for */
static int verify_resp(int num, const char **q, char **a)
static int verify_resp(size_t num, const char **q, char **a)
{
int i;
size_t i;
for (i = 0; i < num; i++) {
if (strcasecmp(q[i], a[i]) != 0) {
@ -1166,11 +1281,11 @@ static int verify_resp(int num, const char **q, char **a)
return 1; /* OK */
}
int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer)
int upscli_get(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer)
{
char cmd[UPSCLI_NETBUF_LEN], tmp[UPSCLI_NETBUF_LEN];
if (!ups) {
return -1;
}
@ -1219,7 +1334,7 @@ int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
return 0;
}
int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query)
int upscli_list_start(UPSCONN_t *ups, size_t numq, const char **query)
{
char cmd[UPSCLI_NETBUF_LEN], tmp[UPSCLI_NETBUF_LEN];
@ -1277,8 +1392,8 @@ int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query)
return 0;
}
int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
unsigned int *numa, char ***answer)
int upscli_list_next(UPSCONN_t *ups, size_t numq, const char **query,
size_t *numa, char ***answer)
{
char tmp[UPSCLI_NETBUF_LEN];
@ -1326,9 +1441,9 @@ int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query,
return 1;
}
int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
ssize_t upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, const time_t timeout)
{
int ret;
ssize_t ret;
if (!ups) {
return -1;
@ -1349,7 +1464,7 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
return -1;
}
ret = net_write(ups, buf, buflen);
ret = net_write(ups, buf, buflen, timeout);
if (ret < 1) {
upscli_disconnect(ups);
@ -1359,9 +1474,14 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
return 0;
}
int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
ssize_t upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen)
{
int ret;
return upscli_sendline_timeout(ups, buf, buflen, 0);
}
ssize_t upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, const time_t timeout)
{
ssize_t ret;
size_t recv;
if (!ups) {
@ -1387,14 +1507,17 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
if (ups->readidx == ups->readlen) {
ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf));
ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf), timeout);
if (ret < 1) {
upscli_disconnect(ups);
return -1;
}
ups->readlen = ret;
/* Here ret is safe to cast since it is >=1 and certainly
* fits under SIZE_MAX being it signed sibling
*/
ups->readlen = (size_t)ret;
ups->readidx = 0;
}
@ -1409,8 +1532,13 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
return 0;
}
ssize_t upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen)
{
return upscli_readline_timeout(ups, buf, buflen, DEFAULT_NETWORK_TIMEOUT);
}
/* split upsname[@hostname[:port]] into separate components */
int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port)
int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t *port)
{
char *s, tmp[SMALLBUF], *last = NULL;
@ -1446,9 +1574,10 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port
}
/* split hostname[:port] into separate components */
int upscli_splitaddr(const char *buf, char **hostname, int *port)
int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port)
{
char *s, tmp[SMALLBUF], *last = NULL;
long l;
/* paranoia */
if ((!buf) || (!hostname) || (!port)) {
@ -1491,10 +1620,13 @@ int upscli_splitaddr(const char *buf, char **hostname, int *port)
}
}
if ((*(++s) == '\0') || ((*port = strtol(s, NULL, 10)) < 1 )) {
/* Check that "long" port fits in an "uint16_t" so is in IP range
* (under 65536) */
if ((*(++s) == '\0') || ((l = strtol(s, NULL, 10)) < 1 ) || (l > 65535)) {
fprintf(stderr, "upscli_splitaddr: no port specified after ':' separator\n");
return -1;
}
*port = (uint16_t)l;
return 0;
}
@ -1518,7 +1650,7 @@ int upscli_disconnect(UPSCONN_t *ups)
return 0;
}
net_write(ups, "LOGOUT\n", 7);
net_write(ups, "LOGOUT\n", 7, 0);
#ifdef WITH_OPENSSL
if (ups->ssl) {

View file

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

View file

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

View file

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

View file

@ -17,25 +17,32 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_UPSIMAGEARG_H_SEEN
#define NUT_UPSIMAGEARG_H_SEEN 1
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
struct {
/* This is used in upsstats.c and in upsimage.c, but compiler complains about
* non-extern definition if this is not "static". To move or not to move?..
* Do we have cases of building binaries refering to only one of those objects?
*/
static struct {
char *name;
int val; /* hex digits, ala HTML */
int min; /* minimum reasonable value */
int max; /* maximum reasonable value */
} imgarg[] =
} 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 },
{ "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 },
@ -47,20 +54,20 @@ struct {
{ "tempmax", 40, -100, 150 },
{ "nom_in_freq", 50, 0, 100 },
{ "nom_out_freq", 50, 0, 100 },
{ NULL, 0, 0, 0 }
{ NULL, 0, 0, 0 }
};
typedef struct {
char *name; /* name of the UPS variable */
char *minimum; /* name of minimum value UPS variable
or variable in imgarg table */
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*);
void (*drawfunc)(double, int, int, int, int, const char*);
} imgvar_t;
extern imgvar_t imgvar[];
@ -71,3 +78,4 @@ extern imgvar_t imgvar[];
/* *INDENT-ON* */
#endif
#endif /* NUT_UPSIMAGEARG_H_SEEN */

View file

@ -20,12 +20,12 @@
/* 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
* 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.
@ -37,9 +37,11 @@
#include "config.h"
#include "timehead.h"
#include "nut_stdint.h"
#include "upslog.h"
static int port, reopen_flag = 0, exit_flag = 0;
static int reopen_flag = 0, exit_flag = 0;
static uint16_t port;
static char *upsname, *hostname;
static UPSCONN_t ups;
@ -79,6 +81,8 @@ static void set_exit_flag(int sig)
static void set_print_now_flag(int sig)
{
NUT_UNUSED_VARIABLE(sig);
/* no need to do anything, the signal will cause sleep to be interrupted */
}
@ -108,6 +112,9 @@ static void setup_signals(void)
fatal_with_errno(EXIT_FAILURE, "Can't install SIGUSR1 handler");
}
static void help(const char *prog)
__attribute__((noreturn));
static void help(const char *prog)
{
printf("UPS status logger.\n");
@ -118,7 +125,9 @@ static void help(const char *prog)
printf(" -f <format> - Log format. See below for details.\n");
printf(" - Use -f \"<format>\" so your shell doesn't break it up.\n");
printf(" -i <interval> - Time between updates, in seconds\n");
printf(" -l <logfile> - Log file name, or - for stdout\n");
printf(" -l <logfile> - Log file name, or - for stdout (foreground by default)\n");
printf(" -F - stay foregrounded even if logging into a file\n");
printf(" -B - stay backgrounded even if logging to stdout\n");
printf(" -p <pidbase> - Base name for PID file (defaults to \"%s\")\n", prog);
printf(" -s <ups> - Monitor UPS <ups> - <upsname>@<host>[:<port>]\n");
printf(" - Example: -s myups@server\n");
@ -146,6 +155,7 @@ static void do_host(const char *arg)
{
int ret;
char hn[LARGEBUF];
NUT_UNUSED_VARIABLE(arg);
ret = gethostname(hn, sizeof(hn));
@ -159,11 +169,15 @@ static void do_host(const char *arg)
static void do_upshost(const char *arg)
{
NUT_UNUSED_VARIABLE(arg);
snprintfcat(logbuffer, sizeof(logbuffer), "%s", monhost);
}
static void do_pid(const char *arg)
{
NUT_UNUSED_VARIABLE(arg);
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (long)getpid());
}
@ -172,6 +186,7 @@ static void do_time(const char *arg)
unsigned int i;
char timebuf[SMALLBUF], *format;
time_t tod;
struct tm tmbuf;
format = xstrdup(arg);
@ -181,7 +196,7 @@ static void do_time(const char *arg)
format[i] = '%';
time(&tod);
strftime(timebuf, sizeof(timebuf), format, localtime(&tod));
strftime(timebuf, sizeof(timebuf), format, localtime_r(&tod, &tmbuf));
snprintfcat(logbuffer, sizeof(logbuffer), "%s", timebuf);
@ -191,7 +206,7 @@ static void do_time(const char *arg)
static void getvar(const char *var)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -235,6 +250,7 @@ static void do_var(const char *arg)
static void do_etime(const char *arg)
{
time_t tod;
NUT_UNUSED_VARIABLE(arg);
time(&tod);
snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (unsigned long) tod);
@ -269,7 +285,7 @@ static void add_call(void (*fptr)(const char *arg), const char *arg)
tmp->next = NULL;
if (last)
last->next = tmp;
last->next = tmp;
else
fhead = tmp;
}
@ -277,8 +293,9 @@ static void add_call(void (*fptr)(const char *arg), const char *arg)
/* turn the format string into a list of function calls with args */
static void compile_format(void)
{
unsigned int i;
int j, found, ofs;
size_t i;
int j, found;
size_t ofs;
char *cmd, *arg, *ptr;
for (i = 0; i < strlen(logformat); i++) {
@ -330,7 +347,7 @@ static void compile_format(void)
/* see if we know how to handle this command */
for (j = 0; logcmds[j].name != NULL; j++) {
if (strncasecmp(cmd, logcmds[j].name,
if (strncasecmp(cmd, logcmds[j].name,
strlen(logcmds[j].name)) == 0) {
add_call(logcmds[j].func, arg);
@ -378,7 +395,7 @@ static void run_flist(void)
int main(int argc, char **argv)
{
int interval = 30, i;
int interval = 30, i, foreground = -1;
const char *prog = xbasename(argv[0]);
time_t now, nextpoll = 0;
const char *user = NULL;
@ -390,11 +407,13 @@ int main(int argc, char **argv)
printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) {
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FB")) != -1) {
switch(i) {
case 'h':
help(prog);
#ifndef HAVE___ATTRIBUTE__NORETURN
break;
#endif
case 's':
monhost = optarg;
@ -422,6 +441,14 @@ int main(int argc, char **argv)
case 'p':
pidfilebase = optarg;
break;
case 'F':
foreground = 1;
break;
case 'B':
foreground = 0;
break;
}
}
@ -462,7 +489,7 @@ int main(int argc, char **argv)
if (!logformat)
fatalx(EXIT_FAILURE, "No format defined - but this should be impossible");
printf("logging status of %s to %s (%is intervals)\n",
printf("logging status of %s to %s (%is intervals)\n",
monhost, logfn, interval);
if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) {
@ -470,7 +497,7 @@ int main(int argc, char **argv)
}
if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0)
fprintf(stderr, "Warning: initial connect failed: %s\n",
fprintf(stderr, "Warning: initial connect failed: %s\n",
upscli_strerror(&ups));
if (strcmp(logfn, "-") == 0)
@ -484,10 +511,19 @@ int main(int argc, char **argv)
/* now drop root if we have it */
new_uid = get_user_pwent(user);
open_syslog(prog);
open_syslog(prog);
if (logfile != stdout)
if (foreground < 0) {
if (logfile == stdout) {
foreground = 1;
} else {
foreground = 0;
}
}
if (!foreground) {
background();
}
setup_signals();
@ -502,7 +538,7 @@ int main(int argc, char **argv)
if (nextpoll > now) {
/* there is still time left, so sleep it off */
sleep(difftime(nextpoll, now));
sleep((unsigned int)(difftime(nextpoll, now)));
nextpoll += interval;
} else {
/* we spent more time in polling than the interval allows */
@ -510,7 +546,7 @@ int main(int argc, char **argv)
}
if (reopen_flag) {
upslogx(LOG_INFO, "Signal %d: reopening log file",
upslogx(LOG_INFO, "Signal %d: reopening log file",
reopen_flag);
reopen_log();
reopen_flag = 0;
@ -535,7 +571,7 @@ int main(int argc, char **argv)
fclose(logfile);
upscli_disconnect(&ups);
exit(EXIT_SUCCESS);
}

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,6 +24,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "nut_stdint.h"
#include "upsclient.h"
#include "cgilib.h"
#include "parseconf.h"
@ -39,12 +40,12 @@ struct list_t {
#define HARD_UPSVAR_LIMIT_NUM 64
#define HARD_UPSVAR_LIMIT_LEN 256
char *monups, *username, *password, *function, *upscommand;
static char *monups, *username, *password, *function, *upscommand;
/* set once the MAGIC_ENABLE_STRING is found in the upsset.conf */
int magic_string_set = 0;
/* set once the MAGIC_ENABLE_STRING is found in the upsset.conf */
static int magic_string_set = 0;
static int port;
static uint16_t port;
static char *upsname, *hostname;
static UPSCONN_t ups;
@ -54,7 +55,7 @@ typedef struct {
void *next;
} uvtype_t;
uvtype_t *firstuv = NULL;
static uvtype_t *firstuv = NULL;
void parsearg(char *var, char *value)
{
@ -134,7 +135,7 @@ static void do_header(const char *title)
printf("<HTML>\n");
printf("<HEAD><TITLE>upsset: %s</TITLE></HEAD>\n", title);
printf("<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000EE\" VLINK=\"#551A8B\">\n");
printf("<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000EE\" VLINK=\"#551A8B\">\n");
printf("<TABLE BGCOLOR=\"#50A0A0\" ALIGN=\"CENTER\">\n");
printf("<TR><TD>\n");
@ -144,7 +145,7 @@ static void start_table(void)
{
printf("<TABLE CELLPADDING=\"5\" CELLSPACING=\"0\" ALIGN=\"CENTER\" WIDTH=\"100%%\">\n");
printf("<TR><TH COLSPAN=2 BGCOLOR=\"#60B0B0\">\n");
printf("<FONT SIZE=\"+2\">Network UPS Tools upsset %s</FONT>\n",
printf("<FONT SIZE=\"+2\">Network UPS Tools upsset %s</FONT>\n",
UPS_VERSION);
printf("</TH></TR>\n");
}
@ -158,12 +159,12 @@ static void do_hidden(const char *next)
password);
if (next)
printf("<INPUT TYPE=\"HIDDEN\" NAME=\"function\" VALUE=\"%s\">\n",
printf("<INPUT TYPE=\"HIDDEN\" NAME=\"function\" VALUE=\"%s\">\n",
next);
}
/* generate SELECT chooser from hosts.conf entries */
static void upslist_arg(int numargs, char **arg)
static void upslist_arg(size_t numargs, char **arg)
{
if (numargs < 3)
return;
@ -222,7 +223,7 @@ static void do_pickups(const char *currfunc)
continue;
}
upslist_arg(ctx.numargs, ctx.arglist);
upslist_arg(ctx.numargs, ctx.arglist);
}
pconf_finish(&ctx);
@ -253,6 +254,10 @@ static void do_pickups(const char *currfunc)
printf("</FORM>\n");
}
static void error_page(const char *next, const char *title,
const char *fmt, ...)
__attribute__((noreturn));
static void error_page(const char *next, const char *title,
const char *fmt, ...)
{
@ -260,7 +265,19 @@ static void error_page(const char *next, const char *title,
va_list ap;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
vsnprintf(msg, sizeof(msg), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
do_header(title);
@ -282,6 +299,9 @@ static void error_page(const char *next, const char *title,
exit(EXIT_SUCCESS);
}
static void loginscreen(void)
__attribute__((noreturn));
static void loginscreen(void)
{
do_header("Login");
@ -331,7 +351,7 @@ static void upsd_connect(void)
static void print_cmd(const char *cmd)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4];
@ -354,7 +374,7 @@ static void print_cmd(const char *cmd)
static void showcmds(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[2];
char **answer;
struct list_t *lhead, *llast, *ltmp, *lnext;
@ -391,7 +411,7 @@ static void showcmds(void)
/* CMD upsname cmdname */
if (numa < 3) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 3)\n", numa);
"(got %zu args, need at least 3)\n", numa);
return;
}
@ -466,7 +486,7 @@ static void showcmds(void)
upscli_disconnect(&ups);
exit(EXIT_SUCCESS);
}
}
/* handle setting authentication data in the server */
static void send_auth(const char *next)
@ -491,7 +511,7 @@ static void send_auth(const char *next)
"upsd version too old - USERNAME not supported");
}
error_page(next, "Can't set user name",
error_page(next, "Can't set user name",
"Set user name failed: %s", upscli_strerror(&ups));
}
@ -504,7 +524,10 @@ static void send_auth(const char *next)
if (upscli_readline(&ups, buf, sizeof(buf)) < 0)
error_page(next, "Can't set password",
"Password set failed: %s", upscli_strerror(&ups));
}
}
static void docmd(void)
__attribute__((noreturn));
static void docmd(void)
{
@ -515,13 +538,13 @@ static void docmd(void)
"Access to that host is not authorized");
/* the user is messing with us */
if (!upscommand)
error_page("showcmds", "Form error",
if (!upscommand)
error_page("showcmds", "Form error",
"No instant command selected");
/* (l)user took the default blank option */
if (strlen(upscommand) == 0)
error_page("showcmds", "Form error",
error_page("showcmds", "Form error",
"No instant command selected");
upsd_connect();
@ -595,7 +618,7 @@ static void docmd(void)
static const char *get_data(const char *type, const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer;
const char *query[4];
@ -633,7 +656,7 @@ static void do_string(const char *varname, int maxlen)
static void do_enum(const char *varname)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
char **answer, *val;
const char *query[4], *tmp;
@ -659,8 +682,9 @@ static void do_enum(const char *varname)
if (ret < 0) {
printf("Unavailable\n");
fprintf(stderr, "Error doing ENUM %s %s: %s\n",
fprintf(stderr, "Error doing ENUM %s %s: %s\n",
upsname, varname, upscli_strerror(&ups));
free(val);
return;
}
@ -674,7 +698,7 @@ static void do_enum(const char *varname)
if (numa < 4) {
fprintf(stderr, "Error: insufficient data "
"(got %d args, need at least 4)\n", numa);
"(got %zu args, need at least 4)\n", numa);
free(val);
return;
@ -697,7 +721,7 @@ static void do_enum(const char *varname)
static void do_type(const char *varname)
{
int ret;
unsigned int i, numq, numa;
size_t i, numq, numa;
char **answer;
const char *query[4];
@ -709,7 +733,7 @@ static void do_type(const char *varname)
ret = upscli_get(&ups, numq, query, &numa, &answer);
if ((ret < 0) || (numa < numq)) {
printf("Unknown type\n");
printf("Unknown type\n");
return;
}
@ -727,7 +751,9 @@ static void do_type(const char *varname)
/* split out the :<len> data */
ptr = strchr(answer[i], ':');
*ptr++ = '\0';
len = strtol(ptr, (char **) NULL, 10);
long l = strtol(ptr, (char **) NULL, 10);
assert(l <= 127); /* FIXME: Loophole about longer numbers? Why are we limited to char at all here? */
len = (char)l;
do_string(varname, len);
return;
@ -741,10 +767,12 @@ static void do_type(const char *varname)
}
}
static void print_rw(const char *upsname, const char *varname)
static void print_rw(const char *arg_upsname, const char *varname)
{
const char *tmp;
printf("<!-- <TR><TD>Device</TD><TD>%s</TD></TR> -->\n", arg_upsname);
printf("<TR BGCOLOR=\"#60B0B0\" ALIGN=\"CENTER\">\n");
printf("<TD>");
@ -765,10 +793,13 @@ static void print_rw(const char *upsname, const char *varname)
printf("</TR>\n");
}
static void showsettings(void)
__attribute__((noreturn));
static void showsettings(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[2];
char **answer, *desc = NULL;
struct list_t *lhead, *llast, *ltmp, *lnext;
@ -907,13 +938,16 @@ static int setvar(const char *var, const char *val)
}
/* turn a form submission of settings into SET commands for upsd */
static void savesettings(void)
__attribute__((noreturn));
static void savesettings(void)
{
int changed = 0;
char *desc;
uvtype_t *upsvar;
if (!checkhost(monups, &desc))
if (!checkhost(monups, &desc))
error_page("showsettings", "Access denied",
"Access to that host is not authorized");
@ -953,6 +987,9 @@ static void savesettings(void)
exit(EXIT_SUCCESS);
}
static void initial_pickups(void)
__attribute__((noreturn));
static void initial_pickups(void)
{
do_header("Select a UPS");
@ -1027,10 +1064,12 @@ static void check_conf(void)
fprintf(stderr, "upsset.conf does not permit execution\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv)
{
NUT_UNUSED_VARIABLE(argc);
NUT_UNUSED_VARIABLE(argv);
username = password = function = monups = NULL;
printf("Content-type: text/html\n\n");
@ -1040,15 +1079,16 @@ int main(int argc, char **argv)
/* see if there's anything waiting .. the server my not close STDIN properly */
if (1) {
fd_set fds;
struct timeval tv;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = 0;
tv.tv_usec = 250000; /* wait for up to 250ms for a POST response */
if ((select(STDIN_FILENO+1, &fds, 0, 0, &tv)) > 0)
extractpostargs();
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = 0;
tv.tv_usec = 250000; /* wait for up to 250ms for a POST response */
if ((select(STDIN_FILENO+1, &fds, 0, 0, &tv)) > 0)
extractpostargs();
}
if ((!username) || (!password) || (!function))
loginscreen();
@ -1074,6 +1114,6 @@ int main(int argc, char **argv)
docmd();
printf("Error: Unhandled function name [%s]\n", function);
return 0;
}

View file

@ -19,11 +19,12 @@
*/
#include "common.h"
#include "nut_stdint.h"
#include "timehead.h"
#include "upsclient.h"
#include "status.h"
#include "cgilib.h"
#include "parseconf.h"
#include "timehead.h"
#include "upsstats.h"
#include "upsimagearg.h"
@ -36,7 +37,7 @@ static int use_celsius = 1, refreshdelay = -1, treemode = 0;
/* from cgilib's checkhost() */
static char *monhostdesc = NULL;
static int port;
static uint16_t port;
static char *upsname, *hostname;
static char *upsimgpath="upsimage.cgi", *upsstatpath="upsstats.cgi";
static UPSCONN_t ups;
@ -103,7 +104,7 @@ static int check_ups_fd(int do_report)
static int get_var(const char *var, char *buf, size_t buflen, int verbose)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -134,7 +135,7 @@ static int get_var(const char *var, char *buf, size_t buflen, int verbose)
if (numa < numq) {
if (verbose)
printf("[Invalid response]\n");
return 0;
}
@ -195,9 +196,10 @@ static int do_date(const char *buf)
{
char datebuf[SMALLBUF];
time_t tod;
struct tm tmbuf;
time(&tod);
if (strftime(datebuf, sizeof(datebuf), buf, localtime(&tod))) {
if (strftime(datebuf, sizeof(datebuf), buf, localtime_r(&tod, &tmbuf))) {
printf("%s", datebuf);
return 1;
}
@ -291,12 +293,12 @@ static int do_img(char *buf)
/* only allow known types through */
if (!strcmp(type, "input.voltage")
|| !strcmp(type, "input.L1-N.voltage")
|| !strcmp(type, "input.L2-N.voltage")
if (!strcmp(type, "input.voltage")
|| !strcmp(type, "input.L1-N.voltage")
|| !strcmp(type, "input.L2-N.voltage")
|| !strcmp(type, "input.L3-N.voltage")
|| !strcmp(type, "input.L1-L2.voltage")
|| !strcmp(type, "input.L2-L3.voltage")
|| !strcmp(type, "input.L1-L2.voltage")
|| !strcmp(type, "input.L2-L3.voltage")
|| !strcmp(type, "input.L3-L1.voltage")) {
return get_img_val(type, "Input voltage", imgargs);
}
@ -308,11 +310,11 @@ static int do_img(char *buf)
return get_img_val(type, "Battery charge", imgargs);
if (!strcmp(type, "output.voltage")
|| !strcmp(type, "output.L1-N.voltage")
|| !strcmp(type, "output.L2-N.voltage")
|| !strcmp(type, "output.L1-N.voltage")
|| !strcmp(type, "output.L2-N.voltage")
|| !strcmp(type, "output.L3-N.voltage")
|| !strcmp(type, "output.L1-L2.voltage")
|| !strcmp(type, "output.L2-L3.voltage")
|| !strcmp(type, "output.L1-L2.voltage")
|| !strcmp(type, "output.L2-L3.voltage")
|| !strcmp(type, "output.L3-L1.voltage")) {
return get_img_val(type, "Output voltage", imgargs);
}
@ -349,7 +351,7 @@ static void ups_connect(void)
{
static ulist_t *lastups = NULL;
char *newups, *newhost;
int newport;
uint16_t newport;
/* try to minimize reconnects */
if (lastups) {
@ -363,13 +365,13 @@ static void ups_connect(void)
/* see if it's just on the same host */
newups = newhost = NULL;
if (upscli_splitname(currups->sys, &newups, &newhost,
if (upscli_splitname(currups->sys, &newups, &newhost,
&newport) != 0) {
printf("Unusable UPS definition [%s]\n", currups->sys);
fprintf(stderr, "Unusable UPS definition [%s]\n",
fprintf(stderr, "Unusable UPS definition [%s]\n",
currups->sys);
exit(EXIT_FAILURE);
}
}
if ((!strcmp(newhost, hostname)) && (port == newport)) {
free(upsname);
@ -564,7 +566,7 @@ static void do_upsimgpath(const char *s) {
static void do_temp(const char *var)
{
char tempc[SMALLBUF];
float tempf;
double tempf;
if (!get_var(var, tempc, sizeof(tempc), 1))
return;
@ -807,7 +809,8 @@ static int do_command(char *cmd)
static void parse_line(const char *buf)
{
char cmd[SMALLBUF];
int i, len, do_cmd = 0;
size_t i, len;
char do_cmd = 0;
for (i = 0; buf[i]; i += len) {
@ -824,9 +827,10 @@ static void parse_line(const char *buf)
i++; /* skip over the '@' character */
continue;
}
assert (len < INT_MAX);
if (do_cmd) {
snprintf(cmd, sizeof(cmd), "%.*s", len, &buf[i]);
snprintf(cmd, sizeof(cmd), "%.*s", (int)len, &buf[i]);
continue;
}
@ -836,13 +840,13 @@ static void parse_line(const char *buf)
}
/* pass it trough */
printf("%.*s", len, &buf[i]);
printf("%.*s", (int)len, &buf[i]);
}
}
static void display_template(const char *tfn)
{
char fn[SMALLBUF], buf[LARGEBUF];
char fn[SMALLBUF], buf[LARGEBUF];
snprintf(fn, sizeof(fn), "%s/%s", confpath(), tfn);
@ -865,7 +869,7 @@ static void display_template(const char *tfn)
static void display_tree(int verbose)
{
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -890,7 +894,7 @@ static void display_tree(int verbose)
printf("<HTML>\n");
printf("<HEAD><TITLE>upsstat: data tree of %s</TITLE></HEAD>\n", currups->desc);
printf("<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000EE\" VLINK=\"#551A8B\">\n");
printf("<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000EE\" VLINK=\"#551A8B\">\n");
printf("<TABLE BGCOLOR=\"#50A0A0\" ALIGN=\"CENTER\">\n");
printf("<TR><TD>\n");
@ -910,12 +914,12 @@ static void display_tree(int verbose)
if (numa < 4) {
if (verbose)
printf("[Invalid response]\n");
return;
}
printf("<TR BGCOLOR=\"#60B0B0\" ALIGN=\"LEFT\">\n");
printf("<TD>%s</TD>\n", answer[2]);
printf("<TD>:</TD>\n");
printf("<TD>%s<br></TD>\n", answer[3]);
@ -936,7 +940,7 @@ static void add_ups(char *sys, char *desc)
tmp = last = ulhead;
while (tmp) {
while (tmp) {
last = tmp;
tmp = tmp->next;
}
@ -1041,9 +1045,12 @@ static void display_single(void)
int main(int argc, char **argv)
{
NUT_UNUSED_VARIABLE(argc);
NUT_UNUSED_VARIABLE(argv);
extractcgiargs();
printf("Content-type: text/html\n");
printf("Content-type: text/html\n");
printf("Pragma: no-cache\n");
printf("\n");

View file

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