Imported Upstream version 2.4.3

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

15
common/Makefile.am Normal file
View file

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

555
common/Makefile.in Normal file
View file

@ -0,0 +1,555 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Network UPS Tools: common
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = common
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
libcommon_a_AR = $(AR) $(ARFLAGS)
libcommon_a_DEPENDENCIES = libparseconf.la
am_libcommon_a_OBJECTS = common.$(OBJEXT) state.$(OBJEXT) \
upsconf.$(OBJEXT)
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libparseconf_la_LIBADD =
am_libparseconf_la_OBJECTS = parseconf.lo
libparseconf_la_OBJECTS = $(am_libparseconf_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libcommon_a_SOURCES) $(libparseconf_la_SOURCES)
DIST_SOURCES = $(libcommon_a_SOURCES) $(libparseconf_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_NAME = @OS_NAME@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
cgiexecdir = @cgiexecdir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
hotplugdir = @hotplugdir@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
AM_CFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = common.c state.c upsconf.c ../include/nut_version.h
libcommon_a_LIBADD = libparseconf.la
noinst_LTLIBRARIES = libparseconf.la
libparseconf_la_SOURCES = parseconf.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu common/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES)
-rm -f libcommon.a
$(libcommon_a_AR) libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD)
$(RANLIB) libcommon.a
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libparseconf.la: $(libparseconf_la_OBJECTS) $(libparseconf_la_DEPENDENCIES)
$(LINK) $(libparseconf_la_OBJECTS) $(libparseconf_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseconf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsconf.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
clean-noinstLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLIBRARIES clean-noinstLTLIBRARIES \
ctags distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am
../include/nut_version.h: FORCE
(cd ../include/ && $(MAKE) $(AM_MAKEFLAGS) nut_version.h)
FORCE:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

540
common/common.c Normal file
View file

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

616
common/parseconf.c Normal file
View file

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

492
common/state.c Normal file
View file

@ -0,0 +1,492 @@
/* state.c - Network UPS Tools common state management functions
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "common.h"
#include "state.h"
#include "parseconf.h"
static void val_escape(struct st_tree_t *node)
{
char etmp[ST_MAX_VALUE_LEN];
/* escape any tricky stuff like \ and " */
pconf_encode(node->raw, etmp, sizeof(etmp));
/* if nothing was escaped, we don't need to do anything else */
if (!strcmp(node->raw, etmp)) {
node->val = node->raw;
return;
}
/* if the escaped value grew, deal with it */
if (node->safesize < (strlen(etmp) + 1)) {
node->safesize = strlen(etmp) + 1;
node->safe = xrealloc(node->safe, node->safesize);
}
snprintf(node->safe, node->safesize, "%s", etmp);
node->val = node->safe;
}
static void st_tree_enum_free(struct enum_t *list)
{
if (!list) {
return;
}
st_tree_enum_free(list->next);
free(list->val);
free(list);
}
/* free all memory associated with a node */
static void st_tree_node_free(struct st_tree_t *node)
{
free(node->var);
free(node->raw);
free(node->safe);
/* never free node->val, since it's just a pointer to raw or safe */
/* blow away the list of enums */
st_tree_enum_free(node->enum_list);
/* now finally kill the node itself */
free(node);
}
/* add a subtree to another subtree */
static void st_tree_node_add(struct st_tree_t **nptr, struct st_tree_t *sptr)
{
if (!sptr) {
return;
}
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, sptr->var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, sptr->var) < 0) {
nptr = &node->right;
continue;
}
upsdebugx(1, "%s: duplicate value (shouldn't happen)", __func__);
return;
}
*nptr = sptr;
}
/* remove a variable from a tree */
int state_delinfo(struct st_tree_t **nptr, const char *var)
{
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
nptr = &node->right;
continue;
}
/* whatever is on the left, hang it off current right */
st_tree_node_add(&node->right, node->left);
/* now point the parent at the old right child */
*nptr = node->right;
st_tree_node_free(node);
return 1;
}
return 0; /* not found */
}
/* interface */
int state_setinfo(struct st_tree_t **nptr, const char *var, const char *val)
{
while (*nptr) {
struct st_tree_t *node = *nptr;
if (strcasecmp(node->var, var) > 0) {
nptr = &node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
nptr = &node->right;
continue;
}
/* updating an existing entry */
if (!strcasecmp(node->raw, val)) {
return 0; /* no change */
}
/* changes should be ignored */
if (node->flags & ST_FLAG_IMMUTABLE) {
return 0; /* no change */
}
/* expand the buffer if the value grows */
if (node->rawsize < (strlen(val) + 1)) {
node->rawsize = strlen(val) + 1;
node->raw = xrealloc(node->raw, node->rawsize);
}
/* store the literal value for later comparisons */
snprintf(node->raw, node->rawsize, "%s", val);
val_escape(node);
return 1; /* changed */
}
*nptr = xcalloc(1, sizeof(**nptr));
(*nptr)->var = xstrdup(var);
(*nptr)->raw = xstrdup(val);
(*nptr)->rawsize = strlen(val) + 1;
val_escape(*nptr);
return 1; /* added */
}
static int st_tree_enum_add(struct enum_t **list, const char *enc)
{
struct enum_t *item;
while (*list) {
if (strcmp((*list)->val, enc)) {
list = &(*list)->next;
continue;
}
return 0; /* duplicate */
}
item = xcalloc(1, sizeof(*item));
item->val = xstrdup(enc);
item->next = *list;
/* now we're done creating it, add it to the list */
*list = item;
return 1; /* added */
}
int state_addenum(struct st_tree_t *root, const char *var, const char *val)
{
struct st_tree_t *sttmp;
char enc[ST_MAX_VALUE_LEN];
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_addenum: base variable (%s) "
"does not exist", var);
return 0; /* failed */
}
/* smooth over any oddities in the enum value */
pconf_encode(val, enc, sizeof(enc));
return st_tree_enum_add(&sttmp->enum_list, enc);
}
int state_setaux(struct st_tree_t *root, const char *var, const char *auxs)
{
struct st_tree_t *sttmp;
int aux;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_addenum: base variable (%s) "
"does not exist", var);
return -1; /* failed */
}
aux = strtol(auxs, (char **) NULL, 10);
/* silently ignore matches */
if (sttmp->aux == aux) {
return 0;
}
sttmp->aux = aux;
return 1;
}
const char *state_getinfo(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return NULL;
}
return sttmp->val;
}
int state_getflags(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return -1;
}
return sttmp->flags;
}
int state_getaux(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return -1;
}
return sttmp->aux;
}
const struct enum_t *state_getenumlist(struct st_tree_t *root, const char *var)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return NULL;
}
return sttmp->enum_list;
}
void state_setflags(struct st_tree_t *root, const char *var, int numflags, char **flag)
{
int i;
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
upslogx(LOG_ERR, "state_setflags: base variable (%s) "
"does not exist", var);
return;
}
sttmp->flags = 0;
for (i = 0; i < numflags; i++) {
if (!strcasecmp(flag[i], "RW")) {
sttmp->flags |= ST_FLAG_RW;
continue;
}
if (!strcasecmp(flag[i], "STRING")) {
sttmp->flags |= ST_FLAG_STRING;
continue;
}
upsdebugx(2, "Unrecognized flag [%s]", flag[i]);
}
}
int state_addcmd(struct cmdlist_t **list, const char *cmd)
{
struct cmdlist_t *item;
while (*list) {
if (strcasecmp((*list)->name, cmd) > 0) {
/* insertion point reached */
break;
}
if (strcasecmp((*list)->name, cmd) < 0) {
list = &(*list)->next;
continue;
}
return 0; /* duplicate */
}
item = xcalloc(1, sizeof(*item));
item->name = xstrdup(cmd);
item->next = *list;
/* now we're done creating it, insert it in the list */
*list = item;
return 1; /* added */
}
void state_infofree(struct st_tree_t *node)
{
if (!node) {
return;
}
state_infofree(node->left);
state_infofree(node->right);
st_tree_node_free(node);
}
void state_cmdfree(struct cmdlist_t *list)
{
if (!list) {
return;
}
state_cmdfree(list->next);
free(list->name);
free(list);
}
int state_delcmd(struct cmdlist_t **list, const char *cmd)
{
while (*list) {
struct cmdlist_t *item = *list;
if (strcasecmp(item->name, cmd) > 0) {
/* not found */
break;
}
if (strcasecmp(item->name, cmd) < 0) {
list = &item->next;
continue;
}
/* we found it! */
*list = item->next;
free(item->name);
free(item);
return 1; /* deleted */
}
return 0; /* not found */
}
static int st_tree_del_enum(struct enum_t **list, const char *val)
{
while (*list) {
struct enum_t *item = *list;
/* if this is not the right value, go on to the next */
if (strcasecmp(item->val, val)) {
list = &item->next;
continue;
}
/* we found it! */
*list = item->next;
free(item->val);
free(item);
return 1; /* deleted */
}
return 0; /* not found */
}
int state_delenum(struct st_tree_t *root, const char *var, const char *val)
{
struct st_tree_t *sttmp;
/* find the tree node for var */
sttmp = state_tree_find(root, var);
if (!sttmp) {
return 0;
}
return st_tree_del_enum(&sttmp->enum_list, val);
}
struct st_tree_t *state_tree_find(struct st_tree_t *node, const char *var)
{
while (node) {
if (strcasecmp(node->var, var) > 0) {
node = node->left;
continue;
}
if (strcasecmp(node->var, var) < 0) {
node = node->right;
continue;
}
break; /* found */
}
return node;
}

107
common/upsconf.c Normal file
View file

@ -0,0 +1,107 @@
/* upsconf.c - code for handling ups.conf ini-style parsing
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "upsconf.h"
#include "common.h"
#include "parseconf.h"
static char *ups_section;
/* handle arguments separated by parseconf */
static void conf_args(int numargs, char **arg)
{
char *ep;
if (numargs < 1)
return;
/* look for section headers - [upsname] */
if ((arg[0][0] == '[') && (arg[0][strlen(arg[0])-1] == ']')) {
free(ups_section);
arg[0][strlen(arg[0])-1] = '\0';
ups_section = xstrdup(&arg[0][1]);
return;
}
/* handle 'foo=bar' (compressed form) */
ep = strchr(arg[0], '=');
if (ep) {
*ep = '\0';
do_upsconf_args(ups_section, arg[0], ep+1);
return;
}
/* handle 'foo' (flag) */
if (numargs == 1) {
do_upsconf_args(ups_section, arg[0], NULL);
return;
}
if (numargs < 3)
return;
/* handle 'foo = bar' (split form) */
if (!strcmp(arg[1], "=")) {
do_upsconf_args(ups_section, arg[0], arg[2]);
return;
}
}
/* called for fatal errors in parseconf like malloc failures */
static void upsconf_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg);
}
/* open the ups.conf, parse it, and call back do_upsconf_args() */
void read_upsconf(void)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
ups_section = NULL;
snprintf(fn, sizeof(fn), "%s/ups.conf", confpath());
pconf_init(&ctx, upsconf_err);
if (!pconf_file_begin(&ctx, fn))
fatalx(EXIT_FAILURE, "Can't open %s: %s", fn, ctx.errmsg);
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
conf_args(ctx.numargs, ctx.arglist);
}
pconf_finish(&ctx);
free(ups_section);
}