new upstream 2.8.0
This commit is contained in:
		
							parent
							
								
									fc7f4b43c1
								
							
						
					
					
						commit
						b2b0c9995a
					
				
					 836 changed files with 137090 additions and 30018 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
}	
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
											
										
									
								
							| 
						 | 
				
			
			@ -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
									
								
							
							
						
						
									
										252
									
								
								clients/nutclientmem.cpp
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										118
									
								
								clients/nutclientmem.h
									
										
									
									
									
										Normal 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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										148
									
								
								clients/upscmd.c
									
										
									
									
									
								
							
							
						
						
									
										148
									
								
								clients/upscmd.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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[] = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										583
									
								
								clients/upsmon.c
									
										
									
									
									
								
							
							
						
						
									
										583
									
								
								clients/upsmon.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										225
									
								
								clients/upsrw.c
									
										
									
									
									
								
							
							
						
						
									
										225
									
								
								clients/upsrw.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										118
									
								
								clients/upsset.c
									
										
									
									
									
								
							
							
						
						
									
										118
									
								
								clients/upsset.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue